#include "mainwindow.h"
#include "ui_mainwindow.h"

// #define MYSQL_TEST

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    this->resize(800,600);

    this->sendTextA.resize(qsizetype(MAXCACHELENGTH));
    this->sendTextA.clear();
    this->recvTextA.resize(qsizetype(MAXCACHELENGTH));
    this->recvTextA.clear();
    this->sendTextB.resize(qsizetype(MAXCACHELENGTH));
    this->sendTextB.clear();
    this->recvTextB.resize(qsizetype(MAXCACHELENGTH));
    this->recvTextB.clear();
    this->expectReturn.resize(qsizetype(1024));
    this->expectReturn.clear();
    this->realReturn.resize(qsizetype(1024));
    this->realReturn.clear();

    this->logA.resize(qsizetype(MAXCACHELENGTH));
    this->logA.clear();
    this->logB.resize(qsizetype(MAXCACHELENGTH));
    this->logB.clear();

    this->updateDialog = new TupdateDialog(this);
    this->dateTime = new QDateTime;
    this->timerSend = new QTimer;
    this->timerSendNbr = new QTimer;
    connect(this->timerSend,SIGNAL(timeout()),this,SLOT(on_btnSerialSend_clicked()));
    connect(this->timerSendNbr,SIGNAL(timeout()),this,SLOT(on_timerSendNbr()));
    this->setWindowTitle("AT命令助手"+QString(TOOLSVERSION));
    this->labelSeiralInfoA = new QLabel("CLOSED");
    this->labelSeiralSendCntA = new QLabel("TX:0");
    this->labelSeiralRevCntA = new QLabel("RX:0");
    this->labelSeiralInfoB = new QLabel("CLOSED");
    this->labelSeiralSendCntB = new QLabel("TX:0");
    this->labelSeiralRevCntB = new QLabel("RX:0");

    this->labelInfoSql=new QLabel();
    this->labelInfoSql->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);

    ui->statusbar->addWidget(this->labelSeiralInfoA);
    ui->statusbar->addWidget(this->labelSeiralSendCntA);
    ui->statusbar->addWidget(this->labelSeiralRevCntA);

    ui->statusbar->addWidget(this->labelSeiralInfoB);
    ui->statusbar->addWidget(this->labelSeiralSendCntB);
    ui->statusbar->addWidget(this->labelSeiralRevCntB);

    connect(ui->menuHelp,SIGNAL(triggered(QAction*)),this,SLOT(on_menuHelpTriggered(QAction*)));
    connect(ui->menuProduct,SIGNAL(triggered(QAction*)),this,SLOT(on_menuProductTriggered(QAction*)));
    ui->actionNormal->setText("蜂窝通用资料");
    ui->action5G->setText("5G产品资料");
    ui->actionCat_1->setText("Cat.1产品资料");
    ui->actionNB->setText("NB产品资料");
    ui->actionfirmware->setText("NB&&Cat.1软件下载");
    ui->actionupgrade->setText("检查升级");
    ui->actionhelp->setText("帮助文档");
    ui->actioninfo->setText("软件信息");
    ui->actionswitchmode->setText("进入测试报告模式");

    this->serialA = new TserialPort();
    connect(this->serialA,SIGNAL(serialStateChanged(int,QString,QString)),this,SLOT(on_serialStateChanged(int,QString,QString)));
    connect(this->serialA,SIGNAL(serialRevReport(QByteArray)),this,SLOT(on_serialRevShowA(QByteArray)),Qt::QueuedConnection);

    this->serialB = new TserialPort();
    connect(this->serialB,SIGNAL(serialStateChanged(int,QString,QString)),this,SLOT(on_serialStateChanged(int,QString,QString)));
    connect(this->serialB,SIGNAL(serialRevReport(QByteArray)),this,SLOT(on_serialRevShowB(QByteArray)),Qt::QueuedConnection);

    this->mutex = new QMutex;
    QMutexLocker locker(this->mutex);
    this->addReturnFlag = true;
    this->messageBox = new QMessageBox;

    ui->lineEditTimerSendCycle->setMaximumWidth(50);
    ui->comboBoxTablesModel->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    ui->comboBoxTablesFunc->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    ui->comboBoxTablesCase->setSizeAdjustPolicy(QComboBox::AdjustToContents);

    ui->comboBoxTablesModel->setView(new QListView());
    ui->comboBoxTablesFunc->setView(new QListView());
    ui->comboBoxTablesCase->setView(new QListView());



    ui->plainTextEditShowHexA->hide();
    ui->plainTextEditShowHexB->hide();
    ui->plainTextEditShowB->hide();
    ui->splitterShow->setStretchFactor(0,2);
    ui->splitterShow->setStretchFactor(1,2);
    ui->splitterShow->setStretchFactor(2,2);
    ui->splitterShow->setStretchFactor(3,2);
    ui->splitterShow->setStretchFactor(4,1);
    QGridLayout *centLayMain = new QGridLayout;
    centLayMain->addWidget(ui->splitterShow,0,0,1,-1);
    centLayMain->addWidget(ui->frameTools,1,0,1,-1);

    centLayMain->addWidget(ui->groupBoxSerial,2,0,1,1,Qt::AlignLeft);
    centLayMain->addWidget(ui->tabWidgetSend,2,1,1,-1,Qt::AlignBottom);

    ui->groupBoxSerial->setStyleSheet("QGroupBox { border: none; }");
    ui->tabWidgetSend->setTabText(0,"数据发送");
    ui->tabWidgetSend->setTabText(1,"文件发送");
    centLayMain->setRowStretch(0,2);
    centLayMain->setRowStretch(1,0);
    centLayMain->setRowStretch(2,0);
    this->centralWidget()->setLayout(centLayMain);
    this->circleCnt = 0;
    this->timerCnt = 0;
    ui->labelCircleCnt->setText(QString("%1").arg(this->circleCnt));
    ui->labelTimerCnt->setText(QString("%1").arg(this->timerCnt));

    QStringList list=QStringList()<<"A:ASCII"<<"A:ASCII&HEX"<<"B:ASCII&HEX"<<"A:ASCII&B:ASCII"<<"A:HEX&&B:HEX"<<"A:ASCII&HEX&&B:ASCII&HEX";
    ui->comboBoxCompare->addItems(list);


    QIcon btnSerialOpenIcon;
    btnSerialOpenIcon.addFile(":/icons/icons/icons8-disconnected-40.png");
    ui->btnSerialOpenA->setIcon(btnSerialOpenIcon);
    ui->btnSerialOpenB->setIcon(btnSerialOpenIcon);

    QIcon btnSerialRefreshIcon;
    btnSerialRefreshIcon.addFile(":/icons/icons/icons8-refresh-64.png");
    ui->btnSerialRefresh->setIcon(btnSerialRefreshIcon);
    ui->btnRefreshTables->setIcon(btnSerialRefreshIcon);

    QIcon btnClearIcon;
    btnClearIcon.addFile(":/icons/icons/clear.png");
    ui->btnClear->setIcon(btnClearIcon);

    QIcon btnSerialSendIcon;
    btnSerialSendIcon.addFile(":/icons/icons/icons8-send-32.png");
    ui->btnSerialSend->setIcon(btnSerialSendIcon);
    ui->btnSendFile->setIcon(btnSerialSendIcon);
    ui->btnSendFile_2->setIcon(btnSerialSendIcon);
    ui->btnSendFile_3->setIcon(btnSerialSendIcon);
    ui->btnSendFile_4->setIcon(btnSerialSendIcon);

    QIcon btnOpenFileIcon;
    btnOpenFileIcon.addFile(":/icons/icons/icons8-file-64.png");
    ui->btnOpenFile->setIcon(btnOpenFileIcon);
    ui->btnOpenFile_2->setIcon(btnOpenFileIcon);
    ui->btnOpenFile_3->setIcon(btnOpenFileIcon);
    ui->btnOpenFile_4->setIcon(btnOpenFileIcon);

    QIcon btnOpenCompareToolsIcon;
    btnOpenCompareToolsIcon.addFile(":/icons/icons/icons8-compare-64.png");
    ui->btnOpenCompareTools->setIcon(btnOpenCompareToolsIcon);


    QIcon btnAddCellIcon;
    btnAddCellIcon.addFile(":/icons/icons/icons8-plus-math-16.png");
    ui->btnAddCell->setIcon(btnAddCellIcon);
    ui->btnAddTables->setIcon(btnAddCellIcon);

    QIcon btnInsertCellIcon;
    btnInsertCellIcon.addFile(":/icons/icons/icons8-insert-48.png");
    ui->btnInsertCell->setIcon(btnInsertCellIcon);

    QIcon btnRemoveCellIcon;
    btnRemoveCellIcon.addFile(":/icons/icons/icons8-remove-48.png");
    ui->btnRemoveCell->setIcon(btnRemoveCellIcon);
    ui->btnDeleteTables->setIcon(btnRemoveCellIcon);

    QIcon btnRenameIcon;
    btnRenameIcon.addFile(":/icons/icons/icons8-rename-100.png");
    ui->btnRenameTables->setIcon(btnRenameIcon);

    QIcon btnSaveLogIcon;
    btnSaveLogIcon.addFile(":/icons/icons/icons8-save-96.png");
    ui->btnSaveLog->setIcon(btnSaveLogIcon);

    QIcon btnSendNbrIcon;
    btnSendNbrIcon.addFile(":/icons/icons/icons8-sequence-96.png");
    ui->btnSendNbr->setIcon(btnSendNbrIcon);

    QIcon btnImportXlsxIcon;
    btnImportXlsxIcon.addFile(":/icons/icons/icons8-xls-import-80.png");
    ui->btnImportCaseXlsx->setIcon(btnImportXlsxIcon);

    QIcon btnExportXlsxIcon;
    btnExportXlsxIcon.addFile(":/icons/icons/icons8-xls-export-80.png");
    ui->btnExportCaseXlsx->setIcon(btnExportXlsxIcon);

    QIcon btnMoveDownIcon;
    btnMoveDownIcon.addFile(":/icons/icons/icons8-double-down-50.png");
    ui->btnMoveDown->setIcon(btnMoveDownIcon);

    QIcon btnMoveUpIcon;
    btnMoveUpIcon.addFile(":/icons/icons/icons8-double-up-50.png");
    ui->btnMoveUp->setIcon(btnMoveUpIcon);

    QIcon btnImportCaseListXlsxIcon;
    btnImportCaseListXlsxIcon.addFile(":/icons/icons/icons8-file-64.png");
    ui->btnImportCaseListXlsx->setIcon(btnImportCaseListXlsxIcon);

    QIcon btnClearCaseListIcon;
    btnClearCaseListIcon.addFile(":/icons/icons/clear.png");
    ui->btnClearCaseList->setIcon(btnClearCaseListIcon);


    QIcon btnStartCaseTestIcon;
    btnStartCaseTestIcon.addFile(":/icons/icons/icons8-go-96.png");
    ui->btnStartCaseTest->setIcon(btnStartCaseTestIcon);


    ui->comboBoxSerialPortA->clear();
    foreach (QSerialPortInfo portInfo, QSerialPortInfo::availablePorts()) {
        ui->comboBoxSerialPortA->addItem(portInfo.portName()+":"+portInfo.description());
        ui->comboBoxSerialPortB->addItem(portInfo.portName()+":"+portInfo.description());
    }
    ui->comboBoxSerialPortA->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
    ui->comboBoxSerialPortA->setView(new QListView());
    comboBox_widthAdjust(ui->comboBoxSerialPortA);

    ui->comboBoxSerialPortB->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
    ui->comboBoxSerialPortB->setView(new QListView());
    comboBox_widthAdjust(ui->comboBoxSerialPortB);

    ui->btnSerialOpenA->setEnabled(ui->comboBoxSerialPortA->count()>0);
	ui->btnSerialOpenB->setEnabled(ui->comboBoxSerialPortA->count()>0);

    ui->comboBoxSerialBaud->clear();
    ui->comboBoxSerialBaud->setMinimumWidth(75);
    foreach (qint32 baud, QSerialPortInfo::standardBaudRates()) {
        ui->comboBoxSerialBaud->addItem(QString::number(baud));
    }
    ui->comboBoxSerialBaud->setCurrentText(QString::number(115200));
    ui->comboBoxSerialBaud->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);

    ui->comboBoxSerialDataBits->clear();
    ui->comboBoxSerialDataBits->addItem(QString::number(QSerialPort::Data8));
    ui->comboBoxSerialDataBits->addItem(QString::number(QSerialPort::Data7));
    ui->comboBoxSerialDataBits->addItem(QString::number(QSerialPort::Data6));
    ui->comboBoxSerialDataBits->addItem(QString::number(QSerialPort::Data5));

    ui->comboBoxSerialPairty->clear();
    ui->comboBoxSerialPairty->addItem("none");
    ui->comboBoxSerialPairty->addItem("even");
    ui->comboBoxSerialPairty->addItem("odd");
    ui->comboBoxSerialPairty->addItem("space");
    ui->comboBoxSerialPairty->addItem("mark");

    ui->comboBoxSerialStop->clear();
    ui->comboBoxSerialStop->addItem("1");
    ui->comboBoxSerialStop->addItem("1.5");
    ui->comboBoxSerialStop->addItem("2");

    QPalette p = ui->plainTextEditShowA->palette();
    p.setColor(QPalette::Base, Qt::black);
    p.setColor(QPalette::Text, Qt::green);
    p.setColor(QPalette::PlaceholderText, Qt::white);
    ui->plainTextEditShowA->setPalette(p);
    ui->plainTextEditShowHexA->setPalette(p);
    p.setColor(QPalette::Text, Qt::yellow);
    ui->plainTextEditShowB->setPalette(p);
    ui->plainTextEditShowHexB->setPalette(p);

    ui->plainTextEditShowA->setMaximumBlockCount(MAXCACHELENGTH);
    ui->plainTextEditShowHexA->setMaximumBlockCount(MAXCACHELENGTH);
    ui->plainTextEditShowB->setMaximumBlockCount(MAXCACHELENGTH);
    ui->plainTextEditShowHexB->setMaximumBlockCount(MAXCACHELENGTH);

    ui->labelSerialPortA->setStyleSheet("color:green;");
    this->labelSeiralInfoA->setStyleSheet("color:green;");
    this->labelSeiralRevCntA->setStyleSheet("color:green;");
    this->labelSeiralSendCntA->setStyleSheet("color:green;");

    QPalette pallette = window()->palette();
    log(INFO,"pallette" + pallette.color(QPalette::Window).name());

    if(pallette.color(QPalette::Window).name() != "#f3f3f3")
    {
        ui->labelSerialPortB->setStyleSheet("color:yellow;");
        this->labelSeiralInfoB->setStyleSheet("color:yellow;");
        this->labelSeiralRevCntB->setStyleSheet("color:yellow;");
        this->labelSeiralSendCntB->setStyleSheet("color:yellow;");
    }


    TFileSave * fileSaveProcess = new TFileSave;
    connect(this,SIGNAL(saveFile(QByteArray,QString)),fileSaveProcess,SLOT(on_saveFile(QByteArray,QString)),Qt::QueuedConnection);

    TLog *log = new TLog();
    connect(this,SIGNAL(savelog(int,QString,QString,QString,int,QString)),log,SLOT(on_saveLog(int,QString,QString,QString,int,QString)));

    m_delegate = new TButtonDelegate;
    // chkboxdelegate = new TCheckBoxDelegate;

    connect(m_delegate,SIGNAL(clicked(int)),this,SLOT(on_itemClick(int)));
    // connect(chkboxdelegate,SIGNAL(clicked(QAbstractItemModel*,QModelIndex)),this,SLOT(on_itemHexClicked(QAbstractItemModel*,QModelIndex)));

    //init sqlite
    createConnection();
    initRelationalTables();
    initSqlModel();
    refreshTableView();

    ui->comboBoxTablesModel->hide();
    ui->comboBoxTablesFunc->hide();
    // ui->btnImportXlsx->hide();
    //退出测试报告模式
    ui->btnImportCaseListXlsx->hide();
    ui->btnClearCaseList->hide();
    ui->btnStartCaseTest->hide();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::comboBox_widthAdjust(QComboBox *cb)
{
    QFontMetrics fm(cb->font());
    int max_len = 0;
    QRect rect;
    for( int i =0;i<cb->count();i++)
    {
        rect = fm.boundingRect(cb->itemText(i));
        if( max_len < rect.width())
        {
            max_len = rect.width();
        }
    }

    if(cb->count() > cb->maxVisibleItems())
    {
        max_len *= 1.8;
    }
    else
    {
        max_len *= 1.2;
    }
    if( max_len < cb->width())
        max_len = cb->width();
    // 设置下拉选项的宽度
    cb->view()->setFixedWidth(max_len);
}
void MainWindow::logRAW(int cate, QString fileName, QString func, int line, QString info)
{
    if(this->logenable)
    {
        emit savelog(cate, this->dateTime->currentDateTime().toString("yyyy.MM.dd hh:mm:ss"), fileName, func, line, info);
    }
    else
    {
        qDebug()<<fileName<<func<<line<<info;
    }
}
void MainWindow::initSqlModel()
{
    this->tabModel = new TSqlRelationalTableModel(this,this->sqlitedb);

    this->tabModel->setTable("at_info");
    this->tabModel->setEditStrategy(QSqlTableModel::OnFieldChange);
    this->tabModel->setFilter(QString("case_id = %1").arg(this->caseMap[ui->comboBoxTablesCase->currentText()]));
    this->tabModel->setSort(this->tabModel->fieldIndex("at_id"),Qt::AscendingOrder);
    this->selModel = new QItemSelectionModel(this->tabModel,this);//应该不需要

    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_id"), Qt::Horizontal, QObject::tr("发送"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("remark"), Qt::Horizontal, QObject::tr("名称"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_cmd"), Qt::Horizontal, QObject::tr("命令"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_return"), Qt::Horizontal, QObject::tr("期望返回值"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("delayms"), Qt::Horizontal, QObject::tr("延时ms"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("script"), Qt::Horizontal, QObject::tr("标志脚本"));
    this->tabModel->select();
    this->sqlRelationalDelegate = new TSqlRelationalDelegate(ui->tableViewSqlite);

    ui->tableViewSqlite->setModel(this->tabModel);
    ui->tableViewSqlite->setSelectionModel(this->selModel);
    ui->tableViewSqlite->setSelectionBehavior(QAbstractItemView::SelectItems);
    ui->tableViewSqlite->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableViewSqlite->setAlternatingRowColors(true);
    ui->tableViewSqlite->setStyleSheet(
        "QTableView::item:selected { background-color: #00bfff; }" // 选中状态
        "QTableView::item:hover { background-color: #0000ff; }" // 鼠标悬停状态
    );
    ui->tableViewSqlite->setItemDelegate(this->sqlRelationalDelegate);
    ui->tableViewSqlite->setItemDelegateForColumn(this->tabModel->fieldIndex("at_id"),m_delegate);
    ui->tableViewSqlite->setItemDelegateForColumn(this->tabModel->fieldIndex("at_return"),new tTextEditDelegate);
    ui->tableViewSqlite->setItemDelegateForColumn(this->tabModel->fieldIndex("script"),new tScriptDelegate);
    // ui->tableViewSqlite->verticalHeader()->setVisible(false);
    ui->tableViewSqlite->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_id"),QHeaderView::Fixed);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_id"),60);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("remark"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("remark"),120);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_cmd"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_cmd"),180);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_return"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_return"),180);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("script"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("script"),120);

    ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("case_id"));
    ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("create_date"));
    ui->tableViewSqlite->show();
    ui->tableViewSqlite->setEditTriggers(QAbstractItemView::DoubleClicked);

}
void MainWindow::refreshTableView()
{

    this->tabModel->setFilter(QString("case_id = %1").arg(this->caseMap[ui->comboBoxTablesCase->currentText()]));
    // this->tabModel->setSort(this->tabModel->fieldIndex("at_id"),Qt::AscendingOrder);
    this->tabModel->initUserData();
    this->tabModel->select();
    log(ERROR,this->tabModel->lastError().text());

}
bool MainWindow::createConnection()
{
    //连接本地数据库
    QString extractTo = QCoreApplication::applicationDirPath();
    QString dbName = QDir::cleanPath(extractTo+QDir::separator()+".."+QDir::separator()+"atCommand.db");
    if(!this->sqlitedb.contains("sqlite"))
    {
        this->sqlitedb = QSqlDatabase::addDatabase("QSQLITE","sqlite");
        this->sqlitedb.setDatabaseName(dbName);
    }
    if(this->sqlitedb.isOpen())
    {
        log(INFO,"本地 sql已连接");
        return true;
    }
    if (!this->sqlitedb.open()) {
        log(ERROR,"本地 sql打开失败");
        return false;
    }
    else
    {
        log(INFO,"本地 sql打开成功");
    }
    return true;
}
bool MainWindow::createModel(QString case_name)
{
    if(ui->comboBoxTablesCase->findText(case_name) != -1)
    {
        this->messageBox->warning(this,"警告","页表已存在");
        return false;
    }
    QSqlQuery query;
    QString sql;
    int case_id=0;
    query = QSqlQuery(this->sqlitedb);
    sql = QString("INSERT INTO case_info(case_name) values('%1');").arg(case_name);
    log(INFO,sql);
    if(!query.exec(sql))
    {
        log(ERROR,query.lastError().text());
    }
    sql = QString("SELECT case_id FROM case_info WHERE case_name='%1';").arg(case_name);
    log(INFO,sql);
    if(query.exec(sql))
    {
        if(query.next())
        {
            case_id = query.value(0).toInt();
        }
    }
    else
    {
        log(ERROR,query.lastError().text());
        this->messageBox->warning(this,"警告","创建页表失败");
        return false;
    }
    log(ERROR,query.lastError().text());

    sql = QString("INSERT INTO at_info(at_id,case_id) VALUES (1,%2),(2,%2),(3,%2),(4,%2),(5,%2),(6,%2),(7,%2),(8,%2),(9,%2),(10,%2);").arg(case_id);
    log(INFO,sql);
    if(!query.exec(sql))
    {
        this->messageBox->warning(this,"警告","插入初始数据失败");
        return false;
    }

    this->caseMap[case_name] = case_id;
    ui->comboBoxTablesCase->addItem(case_name);
    // comboBox_widthAdjust(ui->comboBoxTablesCase);
    ui->comboBoxTablesCase->setCurrentText(case_name);
    return true;
}
bool MainWindow::deleteModel(QString case_name)
{
    int index = ui->comboBoxTablesCase->findText(case_name);
    if( index == -1)
    {
        this->messageBox->warning(this,"警告","页表不存在");
        return false;
    }
    QSqlQuery query;
    query = QSqlQuery(this->sqlitedb);
    query.exec(QString("delete from case_info where case_id=%1;").arg(this->caseMap[case_name]));
    query.exec(QString("delete from at_info where case_id=%1;").arg(this->caseMap[case_name]));
    this->caseMap.remove(case_name);
    ui->comboBoxTablesCase->removeItem(index);
    return true;
}

void MainWindow::initRelationalTables()
{
    QSqlQuery query(this->sqlitedb);
    if(query.exec(QString("SELECT count(*) FROM sqlite_master WHERE type='table';")))
    {
        int tableNbr=0;
        if(query.next())
        {
            tableNbr  = query.value(0).toInt();
        }
        if(tableNbr==0)
        {
            //空表
            query.exec(QString("CREATE TABLE IF NOT EXISTS  case_info( \
                               case_id INTEGER PRIMARY KEY AUTOINCREMENT, \
                               case_name VARCHAR(200) NOT NULL \
                               );"));
            if(!query.exec(QString(" INSERT INTO case_info(case_name) VALUES('基础功能');")))
            {
                log(ERROR,"sqlite INSERT case_info fail");
            }
            query.exec(QString(" CREATE TABLE IF NOT EXISTS  user_info(\
                               id INT PRIMARY KEY NOT NULL UNIQUE,\
                               user_name VARCHAR(100) NOT NULL UNIQUE,\
                               user_password VARCHAR(100) NOT NULL,\
                               corp_name VARCHAR(100) ,\
                               email VARCHAR(100) ,\
                               phone VARCHAR(100),\
                               create_date DATETIME DEFAULT CURRENT_TIMESTAMP \
                               );"));
            if(!query.exec(QString("INSERT INTO user_info(id,user_name,user_password) VALUES(1,'local',''),(2,'admin','');")))
            {
                log(ERROR,"sqlite INSERT user_info fail");
            }
            query.exec(QString("CREATE TABLE at_info(\
                               at_id INT NOT NULL,\
                               remark VARCHAR(200) ,\
                               at_cmd VARCHAR(2000),\
                               at_return VARCHAR(2000) ,\
                               delayms INT DEFAULT 500 ,\
                               script VARCHAR(200) DEFAULT '{\
\r\n\"type\":\"TEXT\",\
\r\n\"crlf\":true,\
\r\n\"count\":1,\
\r\n\"neighbor\":false,\
\r\n\"replace\":\"\",\
\r\n\"onenet\":false,\
\r\n\"ignore\":false\
\r\n}',\
                               case_id INT ,\
                               create_date DATETIME DEFAULT CURRENT_TIMESTAMP,\
                               PRIMARY KEY(at_id,case_id)\
                               );"));


            if(!query.exec(QString("INSERT INTO at_info(at_id,remark,at_cmd,case_id) VALUES(1,'测试','AT',1),(2,'查询模组信息','ATI',1),(3,'查询固件信息','AT+LGSI',1),(4,'查询IMEI','AT+CGSN=1',1);")))
            {
                log(ERROR,"sqlite INSERT at_info fail");
            }

            //测试报告用表
            query.exec(QString("CREATE TABLE IF NOT EXISTS  case_casetestinfo( \
                               case_id INTEGER PRIMARY KEY AUTOINCREMENT, \
                               case_name VARCHAR(200) NOT NULL \
                               );"));
            query.exec(QString("CREATE TABLE at_casetestinfo(\
                               at_id INT NOT NULL,\
                               remark VARCHAR(200) ,\
                               at_cmd VARCHAR(2000),\
                               at_return VARCHAR(2000) ,\
                               delayms INT DEFAULT 500 ,\
                               script VARCHAR(200) DEFAULT '{\
\r\n\"type\":\"TEXT\",\
\r\n\"crlf\":true,\
\r\n\"count\":1,\
\r\n\"neighbor\":false,\
\r\n\"replace\":\"\",\
\r\n\"onenet\":false,\
\r\n\"ignore\":false\
\r\n}',\
                               case_id INT ,\
                               create_date DATETIME DEFAULT CURRENT_TIMESTAMP,\
                               PRIMARY KEY(at_id,case_id)\
                               );"));
        }
        else if(tableNbr==5)
        {
            //旧表
            query.exec(QString("CREATE TABLE at_info_v2(\
                               at_id INT NOT NULL,\
                               remark VARCHAR(200) ,\
                               at_cmd VARCHAR(2000),\
                               at_return VARCHAR(2000) ,\
                               delayms INT DEFAULT 500 ,\
                               script VARCHAR(200) DEFAULT '{\
\r\n\"type\":\"TEXT\",\
\r\n\"crlf\":true,\
\r\n\"count\":1,\
\r\n\"neighbor\":false,\
\r\n\"replace\":\"\",\
\r\n\"onenet\":false,\
\r\n\"ignore\":false\
\r\n}',\
                       case_id INT ,\
                       create_date DATETIME DEFAULT CURRENT_TIMESTAMP,\
                       PRIMARY KEY(at_id,case_id)\
                       );"));

            query.exec(QString("insert into at_info_v2(at_id,remark,at_cmd,at_return,delayms,case_id) select at_id,remark,at_cmd,at_return,delayms,case_id from at_info where delete_date is null;"));
            query.exec(QString("drop table 'at_info';"));
            query.exec(QString("drop table 'privilege_info';"));
            query.exec(QString("alter table 'at_info_v2' rename to 'at_info';"));

            //测试报告用表
            query.exec(QString("CREATE TABLE IF NOT EXISTS  case_casetestinfo( \
                               case_id INTEGER PRIMARY KEY AUTOINCREMENT, \
                               case_name VARCHAR(200) NOT NULL \
                               );"));
            query.exec(QString("CREATE TABLE at_casetestinfo(\
                               at_id INT NOT NULL,\
                               remark VARCHAR(200) ,\
                               at_cmd VARCHAR(2000),\
                               at_return VARCHAR(2000) ,\
                               delayms INT DEFAULT 500 ,\
                               script VARCHAR(200) DEFAULT '{\
\r\n\"type\":\"TEXT\",\
\r\n\"crlf\":true,\
\r\n\"count\":1,\
\r\n\"neighbor\":false,\
\r\n\"replace\":\"\",\
\r\n\"onenet\":false,\
\r\n\"ignore\":false\
\r\n}',\
                               case_id INT ,\
                               create_date DATETIME DEFAULT CURRENT_TIMESTAMP,\
                               PRIMARY KEY(at_id,case_id)\
                               );"));

        }
    }
    if(query.exec(QString("SELECT * from case_info;")))
    {
        ui->comboBoxTablesCase->clear();
        this->caseMap.clear();
        while(query.next())
        {
            QString tableName = query.value(1).toString();
            ui->comboBoxTablesCase->addItem(tableName);
            this->caseMap[tableName] = query.value(0).toInt();
        }
        // comboBox_widthAdjust(ui->comboBoxTablesCase);
    }
}
bool MainWindow::refreshRelationalTables()
{
    QSqlQuery query;
    QString sql;

    query = QSqlQuery(this->sqlitedb);
    sql = QString(" SELECT DISTINCT at_info.case_id,case_info.case_name  FROM at_info JOIN case_info ON case_info.case_id = at_info.case_id WHERE  at_info.delete_date IS NULL ORDER BY at_info.case_id;");
    if(query.exec(sql))
    {
        ui->comboBoxTablesCase->clear();
        this->modelMap.clear();
        while(query.next())
        {
            QString tableName = query.value(1).toString();
            ui->comboBoxTablesCase->addItem(tableName);
            this->modelMap[tableName] = query.value(0).toInt();
        }
    }

    return true;
}

void MainWindow::on_btnSerialRefresh_clicked()
{
    ui->comboBoxSerialPortA->clear();
    ui->comboBoxSerialPortB->clear();
    foreach (QSerialPortInfo portInfo, QSerialPortInfo::availablePorts()) {
        ui->comboBoxSerialPortA->addItem(portInfo.portName()+":"+portInfo.description());
        ui->comboBoxSerialPortB->addItem(portInfo.portName()+":"+portInfo.description());
    }
    comboBox_widthAdjust(ui->comboBoxSerialPortA);
    comboBox_widthAdjust(ui->comboBoxSerialPortB);
    ui->btnSerialOpenA->setEnabled(ui->comboBoxSerialPortA->count()>0);
    ui->btnSerialOpenB->setEnabled(ui->comboBoxSerialPortB->count()>0);
}

void MainWindow::on_btnSerialOpenA_clicked()
{
    if(this->serialStateA)
    {
        this->serialA->closePort();
    }
    else
    {
        QList<QSerialPortInfo> comList = QSerialPortInfo::availablePorts();
        if(comList.length()==0)
        {
            on_btnSerialRefresh_clicked();
            return;
        }
        QSerialPortInfo portInfo = comList.at(ui->comboBoxSerialPortA->currentIndex());
        this->portNameA = portInfo.portName();
        if(this->portNameA == this->portNameB)
        {
            this->portNameA.clear();
            this->messageBox->warning(this,"警告","串口重名");
            return;
        }
        this->baudRate = QSerialPort::BaudRate(ui->comboBoxSerialBaud->currentText().toInt());
        this->dataBits = QSerialPort::DataBits(ui->comboBoxSerialDataBits->currentText().toInt());
        switch (ui->comboBoxSerialPairty->currentIndex()) {
        case 0:
            this->parity = QSerialPort::Parity::NoParity;
            break;
        case 1:
            this->parity = QSerialPort::Parity::EvenParity;
            break;
        case 2:
            this->parity = QSerialPort::Parity::OddParity;
            break;
        case 3:
            this->parity = QSerialPort::Parity::SpaceParity;
            break;
        case 4:
            this->parity = QSerialPort::Parity::MarkParity;
            break;
        default:
            this->parity = QSerialPort::Parity::NoParity;
            break;
        }
        switch (ui->comboBoxSerialStop->currentIndex()) {
        case 0:
            this->stopBits = QSerialPort::StopBits::OneStop;
            break;
        case 1:
            this->stopBits = QSerialPort::StopBits::OneAndHalfStop;
            break;
        case 2:
            this->stopBits = QSerialPort::StopBits::TwoStop;
            break;
        default:
            this->stopBits = QSerialPort::StopBits::OneStop;
            break;
        }
        this->serialA->openPort(this->portNameA, this->baudRate, this->dataBits, this->parity, this->stopBits);
    }
}
void MainWindow::on_btnSerialOpenB_clicked()
{
    if(this->serialStateB)
    {
        this->serialB->closePort();
    }
    else
    {
        QList<QSerialPortInfo> comList = QSerialPortInfo::availablePorts();
        if(comList.length()==0)
        {
            on_btnSerialRefresh_clicked();
            return;
        }
        QSerialPortInfo portInfo = comList.at(ui->comboBoxSerialPortB->currentIndex());
        this->portNameB = portInfo.portName();
        if(this->portNameA == this->portNameB)
        {
            this->portNameB.clear();
            this->messageBox->warning(this,"警告","串口重名");
            return;
        }
        this->baudRate = QSerialPort::BaudRate(ui->comboBoxSerialBaud->currentText().toInt());
        this->dataBits = QSerialPort::DataBits(ui->comboBoxSerialDataBits->currentText().toInt());
        switch (ui->comboBoxSerialPairty->currentIndex()) {
        case 0:
            this->parity = QSerialPort::Parity::NoParity;
            break;
        case 1:
            this->parity = QSerialPort::Parity::EvenParity;
            break;
        case 2:
            this->parity = QSerialPort::Parity::OddParity;
            break;
        case 3:
            this->parity = QSerialPort::Parity::SpaceParity;
            break;
        case 4:
            this->parity = QSerialPort::Parity::MarkParity;
            break;
        default:
            this->parity = QSerialPort::Parity::NoParity;
            break;
        }
        switch (ui->comboBoxSerialStop->currentIndex()) {
        case 0:
            this->stopBits = QSerialPort::StopBits::OneStop;
            break;
        case 1:
            this->stopBits = QSerialPort::StopBits::OneAndHalfStop;
            break;
        case 2:
            this->stopBits = QSerialPort::StopBits::TwoStop;
            break;
        default:
            this->stopBits = QSerialPort::StopBits::OneStop;
            break;
        }
        this->serialB->openPort(this->portNameB, this->baudRate, this->dataBits, this->parity, this->stopBits);
    }
}
void MainWindow::on_btnClear_clicked()
{
    ui->plainTextEditShowA->clear();
    ui->plainTextEditShowHexA->clear();
    ui->plainTextEditShowB->clear();
    ui->plainTextEditShowHexB->clear();
    this->recvTextA.clear();
    this->sendTextA.clear();

    this->logA.clear();
    this->logB.clear();

    this->labelSeiralSendCntA->setText("TX:0");
    this->labelSeiralRevCntA->setText("RX:0");
    this->recvTextB.clear();
    this->sendTextB.clear();
    this->labelSeiralSendCntB->setText("TX:0");
    this->labelSeiralRevCntB->setText("RX:0");
    this->RxCntA = 0;
    this->RxCntB = 0;
    this->TxCntA = 0;
    this->TxCntB = 0;

}

void MainWindow::on_btnSerialSend_clicked()
{
    QString sendBuf = ui->plainTextEditSend->toPlainText();
    sendBuf.replace("\n","\r\n");
    if(this->hexSendFlag)
    {
        sendBuf.remove(" ");
        QByteArray ar = QByteArray::fromHex(sendBuf.toLocal8Bit());
        sendBuf = QString::fromLatin1(ar);
    }
    QByteArray bts = sendBuf.toLatin1();
    if(this->addReturnFlag && this->hexSendFlag ==false)
    {
        bts.append("\r\n");
    }
    uartSend(bts);
    if(this->timerSendFlag)
    {
        this->timerCnt++;
        ui->labelTimerCnt->setText(QString("%1").arg(this->timerCnt));
    }
}

void MainWindow::on_serialRevShowA(QByteArray readBuf)
{

    QString plainText;
    QString plainTextHex;
    static qint64 lasttick=0;
    qint64 curtick = QDateTime::currentMSecsSinceEpoch();
    this->recvTextA.append(readBuf);
    QString datetime =  this->dateTime->currentDateTime().toString("hh:mm:ss.zzz");

    //校验接受数据是否是期望返回数据
    if(!this->expectReturn.isEmpty())
    {
        this->realReturn.append(readBuf);
        if(this->realReturn.indexOf(this->expectReturn) != -1)
        {

            this->tabModel->setData(this->curIndex,false,Qt::UserRole+1);
            if(this->rowCaseTestList)
            {
                QVariant writeValue = this->realReturn;
                this->xlsxDoc->write(this->rowNbrCur+2,6,writeValue.toString());
                QXlsx::Format bakgroundColor;
                bakgroundColor.setPatternBackgroundColor(Qt::green);
                this->xlsxDoc->write(this->rowNbrCur+2,7,"Pass", bakgroundColor);
            }

        }
        else
        {

            this->tabModel->setData(this->curIndex,true,Qt::UserRole+1);
            if(this->rowCaseTestList)
            {
                QVariant writeValue = this->realReturn;
                this->xlsxDoc->write(this->rowNbrCur+2,6,writeValue.toString());
                QXlsx::Format bakgroundColor;
                bakgroundColor.setPatternBackgroundColor(Qt::red);
                this->xlsxDoc->write(this->rowNbrCur+2,7,"Fail", bakgroundColor);
            }
        }
    }
    if(curtick - lasttick > TICKOUT)
    {
        // qDebug()<<curtick<<lasttick;
        this->logA.append(QString("\n["+datetime+"]Rx<-◆\n").toLocal8Bit());
    }
    this->logA.append(readBuf);
    QByteArray ar;
    ar = readBuf.toHex();
    plainText = QString::fromUtf8(readBuf);
    plainTextHex = QString::fromUtf8(ar);
    int n = plainTextHex.length();
    while(n>1)
    {
        plainTextHex.insert(n," ");
        n = n-2;
    }
    this->mutex->lock();
    ui->plainTextEditShowHexA->moveCursor(QTextCursor::End);
    ui->plainTextEditShowA->moveCursor(QTextCursor::End);
    if(this->addTimeStampFlag && (curtick - lasttick > TICKOUT))
    {
        ui->plainTextEditShowHexA->insertPlainText("\n["+datetime+"]Rx<-◆\n"+plainTextHex);
        ui->plainTextEditShowA->insertPlainText("\n["+datetime+"]Rx<-◆\n"+plainText);
    }
    else
    {
        ui->plainTextEditShowHexA->insertPlainText(plainTextHex);
        if(plainText[0]=='\n')
        {
            int pos = this->recvTextA.lastIndexOf(readBuf);
            if(pos>0 && this->recvTextA[pos-1] == '\r')
            {
                plainText.removeAt(0);
            }
        }
        ui->plainTextEditShowA->insertPlainText(plainText);
    }
    int length=this->recvTextA.length();
    if(length>MAXLOGLENGTH)
    {
        emit saveFile(this->recvTextA,"串口A原始接收");
        this->recvTextA.clear();
        emit saveFile(ui->plainTextEditShowHexA->toPlainText().toLocal8Bit(),"串口A窗口HEX显示");
        ui->plainTextEditShowHexA->clear();
        emit saveFile(ui->plainTextEditShowA->toPlainText().toLocal8Bit(),"串口A窗口TEXT显示");
        ui->plainTextEditShowA->clear();
        this->RxCntA += length;
        length = this->RxCntA;
    }
    else
    {
        length += this->RxCntA;
    }


    ui->plainTextEditShowHexA->moveCursor(QTextCursor::End);
    ui->plainTextEditShowA->moveCursor(QTextCursor::End);
    ui->plainTextEditShowHexB->moveCursor(QTextCursor::End);
    ui->plainTextEditShowB->moveCursor(QTextCursor::End);
    this->labelSeiralRevCntA->setText(QString("RX:%1").arg(length));
    this->mutex->unlock();
    lasttick = curtick;
}
void MainWindow::on_serialRevShowB(QByteArray readBuf)
{

    QString plainText;
    QString plainTextHex;
    static qint64 lasttick=0;
    qint64 curtick = QDateTime::currentMSecsSinceEpoch();
    this->recvTextB.append(readBuf);
    QString datetime =  this->dateTime->currentDateTime().toString("hh:mm:ss.zzz");
    if(curtick - lasttick > TICKOUT)
    {
        this->logB.append(QString("\n["+datetime+"]Rx<-◆\n").toLocal8Bit());
    }
    this->logB.append(readBuf);

    QByteArray ar;
    //会出现接收\r\n分开接收的情况变成两个回车换行
    ar = readBuf.toHex();
    plainText = QString::fromUtf8(readBuf);
    plainTextHex = QString::fromUtf8(ar);
    int n = plainTextHex.length();
    while(n>1)
    {
        plainTextHex.insert(n," ");
        n = n-2;
    }
    this->mutex->lock();
    ui->plainTextEditShowHexB->moveCursor(QTextCursor::End);
    ui->plainTextEditShowB->moveCursor(QTextCursor::End);
    if(this->addTimeStampFlag && (curtick - lasttick > TICKOUT))
    {
        ui->plainTextEditShowHexB->insertPlainText("\n["+datetime+"]Rx<-◆\n"+plainTextHex);
        ui->plainTextEditShowB->insertPlainText("\n["+datetime+"]Rx<-◆\n"+plainText);
    }
    else
    {
        //如果打开上文《会出现，接收数据量大的时候显示不流畅》部分代码，则改为setPlainText
        ui->plainTextEditShowHexB->insertPlainText(plainTextHex);
        if(plainText[0]=='\n')
        {
            int pos = this->recvTextB.lastIndexOf(readBuf);
            if(pos>0 && this->recvTextB[pos-1] == '\r')
            {
                plainText.removeAt(0);
            }
        }
        ui->plainTextEditShowB->insertPlainText(plainText);
    }
    int length=this->recvTextB.length();
    if(length>MAXLOGLENGTH)
    {
        emit saveFile(this->recvTextB,"串口B原始接收");
        this->recvTextB.clear();
        emit saveFile(ui->plainTextEditShowHexB->toPlainText().toLocal8Bit(),"串口B窗口HEX显示");
        ui->plainTextEditShowHexB->clear();
        emit saveFile(ui->plainTextEditShowB->toPlainText().toLocal8Bit(),"串口B窗口TEXT显示");
        ui->plainTextEditShowB->clear();
        this->RxCntB += length;
        length = this->RxCntB;
    }
    else
    {
        length += this->RxCntB;
    }

    ui->plainTextEditShowHexA->moveCursor(QTextCursor::End);
    ui->plainTextEditShowA->moveCursor(QTextCursor::End);
    ui->plainTextEditShowHexB->moveCursor(QTextCursor::End);
    ui->plainTextEditShowB->moveCursor(QTextCursor::End);
    this->labelSeiralRevCntB->setText(QString("RX:%1").arg(length));
    this->mutex->unlock();
    lasttick = curtick;
}
void MainWindow::uartSend(QByteArray bts,QByteArray btsB)
{
    if(!this->serialStateA && !this->serialStateB)
    {
        return;
    }
    QString datetime =  this->dateTime->currentDateTime().toString("hh:mm:ss.zzz");
    if(this->serialStateA)
    {
        this->serialA->writeData(bts);
        this->sendTextA.append(bts);
        this->logA.append(QString("\n["+datetime+"]Tx->◇\n").toLocal8Bit());
        this->logA.append(bts);
    }
    if(this->serialStateB)
    {
        if(btsB.isEmpty())
        {
            this->serialB->writeData(bts);
            this->sendTextB.append(bts);
            this->logB.append(QString("\n["+datetime+"]Tx->◇\n").toLocal8Bit());
            this->logB.append(bts);
        }
        else
        {
            this->serialB->writeData(btsB);
            this->sendTextB.append(btsB);
            this->logB.append(QString("\n["+datetime+"]Tx->◇\n").toLocal8Bit());
            this->logB.append(btsB);
        }
    }

    if(this->addRxTxFlag)
    {
        if(this->serialStateA)
        {
            QByteArray ar;
            ar = bts.toHex();
            QString textHex = QString::fromUtf8(ar);
            int n = textHex.length();
            while(n>1)
            {
                textHex.insert(n," ");
                n = n-2;
            }
            QString sendTime;
            if(this->addTimeStampFlag)
            {
                sendTime = QString("\n["+datetime+"]Tx->◇\n");
            }
            this->mutex->lock();
            ui->plainTextEditShowHexA->moveCursor(QTextCursor::End);
            ui->plainTextEditShowA->moveCursor(QTextCursor::End);
            ui->plainTextEditShowHexA->insertPlainText(sendTime+textHex);
            ui->plainTextEditShowA->insertPlainText(sendTime+QString::fromLocal8Bit(bts));
            ui->plainTextEditShowHexA->moveCursor(QTextCursor::End);
            ui->plainTextEditShowA->moveCursor(QTextCursor::End);
            this->mutex->unlock();
        }
        if(this->serialStateB)
        {
            if(!btsB.isEmpty())
            {
                bts = btsB;
            }
            QByteArray ar;
            ar = bts.toHex();
            QString textHex = QString::fromUtf8(ar);
            int n = textHex.length();
            while(n>1)
            {
                textHex.insert(n," ");
                n = n-2;
            }
            QString sendTime;
            if(this->addTimeStampFlag)
            {
                sendTime = QString("\n["+datetime+"]Tx->◇\n");
            }
            this->mutex->lock();
            ui->plainTextEditShowHexB->moveCursor(QTextCursor::End);
            ui->plainTextEditShowB->moveCursor(QTextCursor::End);
            ui->plainTextEditShowHexB->insertPlainText(sendTime+textHex);
            ui->plainTextEditShowB->insertPlainText(sendTime+QString::fromLocal8Bit(bts));
            ui->plainTextEditShowHexB->moveCursor(QTextCursor::End);
            ui->plainTextEditShowB->moveCursor(QTextCursor::End);
            this->mutex->unlock();
        }

    }
    int length;
    if(this->serialStateA)
    {
        length = this->sendTextA.length();
        if(length>MAXLOGLENGTH)
        {
            emit saveFile(this->sendTextA,"串口A原始发送数据");
            this->sendTextA.clear();
            emit saveFile(this->logA,"串口A收发日志");
            this->logA.clear();
            this->TxCntA += length;
            length = this->TxCntA;
        }
        else
        {
            length += this->TxCntA;
        }
        this->labelSeiralSendCntA->setText(QString("TX:%1").arg(length));
    }
    if(this->serialStateB)
    {
        length = this->sendTextB.length();
        if(length>MAXLOGLENGTH)
        {
            emit saveFile(this->sendTextB,"串口B原始发送数据");
            this->sendTextB.clear();
            emit saveFile(this->logB,"串口B收发日志");
            this->logB.clear();
            this->TxCntB += length;
            length = this->TxCntB;
        }
        else
        {
            length += this->TxCntB;
        }
        this->labelSeiralSendCntB->setText(QString("TX:%1").arg(length));
    }
}



void MainWindow::on_chkBoxAddReturn_clicked(bool checked)
{
    if(checked)
    {
        this->addReturnFlag = true;
    }
    else
    {
        this->addReturnFlag = false;
    }
}

void MainWindow::on_btnInsertCell_clicked()
{
    int row,maxrow;
    int at_id;
    if(this->caseMap[ui->comboBoxTablesCase->currentText()] == 0)
    {
        this->messageBox->warning(this,"警告","请先设置case名称");
        return;
    }
    row = this->selModel->currentIndex().row();
    maxrow = this->tabModel->rowCount();
    for(int editrow = maxrow-1;editrow>row;editrow--)
    {
        at_id = this->tabModel->index(editrow,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
        this->tabModel->setData(this->tabModel->index(editrow,this->tabModel->fieldIndex("at_id")),at_id+1);
    }
    bool res = this->tabModel->submitAll();
    if(!res)
    {
        this->messageBox->warning(this,"警告","插入失败1");
        this->labelInfoSql->setText("submit fail");
    }
    at_id = this->tabModel->index(row,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
    this->tabModel->insertRow(row);
    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("at_id")),at_id+1);
    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("case_id")),this->caseMap[ui->comboBoxTablesCase->currentText()]);

    res = this->tabModel->submitAll();
    if(!res)
    {
        this->messageBox->warning(this,"警告","插入失败2");
        this->labelInfoSql->setText("submit fail");
    }
    this->tabModel->select();
    this->selModel->setCurrentIndex(this->tabModel->index(row,this->tabModel->fieldIndex("remark")),QItemSelectionModel::Select);

    return;
}


void MainWindow::on_btnAddCell_clicked()
{
    int row;
    int at_id;
    if(this->caseMap[ui->comboBoxTablesCase->currentText()] == 0)
    {
        this->messageBox->warning(this,"警告","请先设置case名称");
        return;
    }

    row = this->tabModel->rowCount();
    at_id = this->tabModel->index(row-1,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
    for(int i=0;i<10;i++)
    {
        at_id++;
        this->tabModel->insertRow(row+i);
        this->tabModel->setData(this->tabModel->index(row+i,this->tabModel->fieldIndex("at_id")),at_id);
        this->tabModel->setData(this->tabModel->index(row+i,this->tabModel->fieldIndex("case_id")),this->caseMap[ui->comboBoxTablesCase->currentText()]);
        this->tabModel->submit();
    }
    this->tabModel->submitAll();
    this->selModel->setCurrentIndex(this->tabModel->index(row,this->tabModel->fieldIndex("remark")),QItemSelectionModel::Select);
    this->labelInfoSql->setText("add"+QString("%1").arg(row));
}


void MainWindow::on_btnRemoveCell_clicked()
{
    int row;
    QModelIndex curIdex;
    row = this->selModel->currentIndex().row();
    this->tabModel->removeRow(row);
    this->tabModel->submitAll();
    this->tabModel->select();

    this->selModel->setCurrentIndex(this->tabModel->index(row,this->tabModel->fieldIndex("remark")),QItemSelectionModel::Select);
    this->labelInfoSql->setText("remove:"+QString("%1").arg(row));
}


void MainWindow::on_itemClick(int row)
{
    QString sendBuf;
    QString sendBufB;
    QString script;
    QVariantMap jsonMap;
    script = this->tabModel->index(row,this->tabModel->fieldIndex("script")).data().toString();
    sendBuf = this->tabModel->index(row,this->tabModel->fieldIndex("at_cmd")).data().toString();
    this->curIndex = this->tabModel->index(row,this->tabModel->fieldIndex("at_return"));
    this->expectReturn = this->curIndex.data().toString().toLocal8Bit();
    this->realReturn.clear();

    tJson json;
    if(!json.validateJson(script))
    {
        this->messageBox->warning(this,"警告","json脚本错误");
        return;
    }
    this->scriptJson = json.jsonStringToDict(script);

    if(this->scriptJson["replace"].toString() != "")
    {
        sendBufB=sendBuf;
        sendBuf.replace(jsonMap["replace"].toString(),"A");
        sendBufB.replace(jsonMap["replace"].toString(),"B");
    }
    if(this->rowCaseTestList)
    {
        //测试报告模式
        QVariant writeValue;
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("remark")).data(Qt::DisplayRole).toString();
        this->xlsxDoc->write(this->rowNbr+2,1,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("at_cmd")).data(Qt::DisplayRole).toString();
        this->xlsxDoc->write(this->rowNbr+2,2,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("at_return")).data(Qt::DisplayRole).toString();
        this->xlsxDoc->write(this->rowNbr+2,3,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("delayms")).data(Qt::DisplayRole).toInt();
        this->xlsxDoc->write(this->rowNbr+2,4,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("script")).data(Qt::DisplayRole).toString();
        this->xlsxDoc->write(this->rowNbr+2,5,writeValue);
    }
    //忽略空命令行
    if(sendBuf.isEmpty())
    {
        return;
    }

    if(sendBufB.isEmpty())
    {
        QByteArray bts = sendBuf.toLatin1();
        if(this->scriptJson["type"]=="HEX"||this->scriptJson["type"]=="hex")
        {
            sendBuf.remove(" ");
            QByteArray ar = QByteArray::fromHex(sendBuf.toLatin1());
            sendBuf = QString::fromLatin1(ar);
            bts = sendBuf.toLatin1();
        }
        if(this->scriptJson["crlf"].toBool())
        {
            bts.append("\r\n");
        }
        uartSend(bts);
    }
    else
    {
        QByteArray bts = sendBuf.toLatin1();
        QByteArray btsB = sendBufB.toLatin1();
        if(this->scriptJson["type"]=="HEX"||this->scriptJson["type"]=="hex")
        {
            sendBuf.remove(" ");
            sendBufB.remove(" ");
            QByteArray ar = QByteArray::fromHex(sendBuf.toLatin1());
            sendBuf = QString::fromLatin1(ar);
            bts = sendBuf.toLatin1();

            ar = QByteArray::fromHex(sendBuf.toLatin1());
            sendBufB = QString::fromLatin1(ar);
            btsB = sendBuf.toLatin1();
        }
        if(this->scriptJson["crlf"].toBool())
        {
            bts.append("\r\n");
            btsB.append("\r\n");
        }
        uartSend(bts,btsB);
    }
}

void MainWindow::on_itemHexClicked(QAbstractItemModel *model,const QModelIndex &index)
{

    ui->tableViewSqlite->setCurrentIndex(index);
    model->setData(index,QVariant(!index.data().toBool()));
}

void MainWindow::on_chkBoxAddTimeStamp_clicked(bool checked)
{
    this->addTimeStampFlag = checked;
}


void MainWindow::on_serialStateChanged(const int state,const QString portName,const QString info)
{
    QIcon btnSerialOpenIcon;
    QList<QSerialPortInfo> comList;
    QSerialPortInfo portInfo;
    QString serialTip;
    Q_UNUSED(info);
    switch(state)
    {
    case 0:
        btnSerialOpenIcon.addFile(":/icons/icons/icons8-disconnected-40.png");
        if(portName == this->portNameA)
        {
            this->serialStateA = false;
            ui->btnSerialOpenA->setIcon(btnSerialOpenIcon);
            ui->comboBoxSerialPortA->setEnabled(true);
        }
        if(portName == this->portNameB)
        {
            this->serialStateB = false;
            ui->btnSerialOpenB->setIcon(btnSerialOpenIcon);
            ui->comboBoxSerialPortB->setEnabled(true);
        }
        if(!this->serialStateA && !this->serialStateB)
        {
            ui->btnSerialRefresh->setEnabled(true);
            ui->comboBoxSerialBaud->setEnabled(true);
            ui->comboBoxSerialDataBits->setEnabled(true);
            ui->comboBoxSerialPairty->setEnabled(true);
            ui->comboBoxSerialStop->setEnabled(true);
        }
        if(portName == this->portNameA)
        {
            this->labelSeiralInfoA->clear();
            this->portNameA.clear();
        }
        if(portName == this->portNameB)
        {
            this->labelSeiralInfoB->clear();
            this->portNameB.clear();
        }
        if(!this->serialStateA && !this->serialStateB)
        {
            ui->chkBoxSendCircle->setChecked(false);
            ui->chkBoxTimerSend->setChecked(false);
            this->rowCricle=false;
            this->rowNbr = this->rowCnt;
            this->timerSend->stop();
            this->timerSendNbr->stop();
            ui->chkBoxSendCircle->setEnabled(true);
            ui->chkBoxTimerSend->setEnabled(true);
            ui->btnSendNbr->setEnabled(true);
            ui->lineEditTimerSendCycle->setEnabled(true);
        }
        break;
    case 1:
        comList = QSerialPortInfo::availablePorts();
        btnSerialOpenIcon.addFile(":/icons/icons/icons8-connect-40.png");
        if(portName == this->portNameA)
        {
            this->serialStateA = true;
            portInfo = comList.at(ui->comboBoxSerialPortA->currentIndex());
            ui->btnSerialOpenA->setIcon(btnSerialOpenIcon);
            ui->comboBoxSerialPortA->setEnabled(false);

        }
        if(portName == this->portNameB)
        {
            this->serialStateB = true;
            portInfo = comList.at(ui->comboBoxSerialPortB->currentIndex());
            ui->btnSerialOpenB->setIcon(btnSerialOpenIcon);
            ui->comboBoxSerialPortB->setEnabled(false);

        }

        ui->btnSerialRefresh->setEnabled(false);
        ui->comboBoxSerialBaud->setEnabled(false);
        ui->comboBoxSerialDataBits->setEnabled(false);
        ui->comboBoxSerialPairty->setEnabled(false);
        ui->comboBoxSerialStop->setEnabled(false);
        serialTip=portInfo.portName()+":"+portInfo.description()
                    +" "+ui->comboBoxSerialBaud->currentText()
                    +" "+ui->comboBoxSerialDataBits->currentText()
                    +" "+ui->comboBoxSerialPairty->currentText()
                    +" "+ui->comboBoxSerialStop->currentText();
        if(portName == this->portNameA)
        {
            this->labelSeiralInfoA->setText(serialTip);
        }
        if(portName == this->portNameB)
        {
            this->labelSeiralInfoB->setText(serialTip);
        }
        break;
     case 2:
        btnSerialOpenIcon.addFile(":/icons/icons/icons8-disconnected-40.png");
        if(portName == this->portNameA)
        {
            this->serialStateA = false;
            foreach (QSerialPortInfo portInfo, QSerialPortInfo::availablePorts()) {
                ui->comboBoxSerialPortA->addItem(portInfo.portName()+":"+portInfo.description());
            }
            ui->btnSerialOpenA->setIcon(btnSerialOpenIcon);
            comboBox_widthAdjust(ui->comboBoxSerialPortA);
            ui->comboBoxSerialPortA->setEnabled(true);
            this->portNameA.clear();
        }
        if(portName == this->portNameB)
        {
            this->serialStateB = false;
            foreach (QSerialPortInfo portInfo, QSerialPortInfo::availablePorts()) {
                ui->comboBoxSerialPortB->addItem(portInfo.portName()+":"+portInfo.description());
            }
            ui->btnSerialOpenB->setIcon(btnSerialOpenIcon);
            comboBox_widthAdjust(ui->comboBoxSerialPortB);
            ui->comboBoxSerialPortB->setEnabled(true);
            this->portNameB.clear();
        }
        if(!this->serialStateA && !this->serialStateB)
        {
            ui->btnSerialRefresh->setEnabled(true);
            ui->comboBoxSerialBaud->setEnabled(true);
            ui->comboBoxSerialDataBits->setEnabled(true);
            ui->comboBoxSerialPairty->setEnabled(true);
            ui->comboBoxSerialStop->setEnabled(true);
        }
        break;
    default :
        break;
    }
}

void MainWindow::on_btnSaveLog_clicked()
{
    emit saveFile(this->logA,"串口A收发日志");
    emit saveFile(this->logB,"串口B收发日志");


    emit saveFile(this->recvTextA,"串口A原始接收");
    //this->recvTextA.clear();

    emit saveFile(this->sendTextA,"串口A原始发送数据");
    //this->sendTextA.clear();

    emit saveFile(ui->plainTextEditShowA->toPlainText().toLocal8Bit(),"串口A窗口TEXT显示");
    //ui->plainTextEditShowA->clear();

    emit saveFile(ui->plainTextEditShowHexA->toPlainText().toLocal8Bit(),"串口A窗口HEX显示");
    //ui->plainTextEditShowHexA->clear();

    emit saveFile(this->recvTextB,"串口B原始接收");
    //this->recvTextB.clear();

    emit saveFile(this->sendTextB,"串口B原始发送数据");
    //this->sendTextB.clear();

    emit saveFile(ui->plainTextEditShowB->toPlainText().toLocal8Bit(),"串口B窗口TEXT显示");
    //ui->plainTextEditShowB->clear();

    emit saveFile(ui->plainTextEditShowHexB->toPlainText().toLocal8Bit(),"串口B窗口HEX显示");
    //ui->plainTextEditShowHexB->clear();

    this->messageBox->information(this,"报告","日志保存成功");
}



void MainWindow::on_chkBoxTimerSend_clicked(bool checked)
{
    if(!this->serialStateA && !this->serialStateA)
    {
        ui->chkBoxTimerSend->setChecked(false);
        this->messageBox->warning(this,"警告","串口未打开");
        return;
    }
    if(checked)
    {
        this->timerSendFlag = true;
        if(!this->timerSend->isActive())
        {
            ui->chkBoxTimerSend->setEnabled(true);
            ui->chkBoxSendCircle->setEnabled(false);
            ui->btnSendNbr->setEnabled(false);

            this->timerCnt = 0;
            ui->labelTimerCnt->setText(QString("%1").arg(this->timerCnt));
            this->timerSend->start(ui->lineEditTimerSendCycle->text().toInt());
        }
        ui->lineEditTimerSendCycle->setEnabled(false);
    }
    else
    {
        this->rowCricle=false;
        this->rowNbr = this->rowCnt;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        this->timerSendFlag = false;
        this->timerSend->stop();
        ui->lineEditTimerSendCycle->setEnabled(true);
    }
}


void MainWindow::on_btnSendNbr_clicked()
{
    if(!this->serialStateA && !this->serialStateA)
    {
        this->messageBox->warning(this,"警告","串口未打开");
        return;
    }
    if(this->rowCricle)
    {
        return;
    }
    this->timerSend->stop();
    ui->btnSendNbr->setEnabled(true);
    ui->chkBoxSendCircle->setEnabled(false);
    ui->chkBoxTimerSend->setEnabled(false);

    this->rowCnt = this->tabModel->rowCount();

    this->rowNbr=0;
    this->timerSendNbr->singleShot(1,Qt::CoarseTimer,this,SLOT(on_timerSendNbr()));
}
void MainWindow::on_chkBoxSendCircle_clicked(bool checked)
{
    if(checked == true && !this->serialStateA && !this->serialStateB)
    {
        this->rowCricle=false;
        this->rowNbr = this->rowCnt;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        this->messageBox->warning(this,"警告","串口未打开");
        return;
    }
    if(!checked)
    {
        this->rowCricle=false;
        this->rowNbr = this->rowCnt;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        return;
    }
    this->timerSend->stop();
    ui->chkBoxSendCircle->setEnabled(true);
    ui->chkBoxTimerSend->setEnabled(false);
    ui->btnSendNbr->setEnabled(false);
    this->rowCnt = this->tabModel->rowCount();

    this->rowNbr=0;
    this->rowCricle=true;
    this->circleCnt = 0;
    ui->labelCircleCnt->setText(QString("%1").arg(this->circleCnt));
    this->timerSendNbr->singleShot(1,Qt::CoarseTimer,this,SLOT(on_timerSendNbr()));
}

void MainWindow::on_timerSendNbr()
{
    int delayms;
    QString script;
    QString sendBuf;
    static QMap<int,int> caseLoopCnt;
/*****************IGNORE_LOOP start************************/
IGNORE_LOOP:
    if(this->rowNbr == this->rowCnt && this->rowCricle)
    {
        this->rowNbr = 0;
        this->circleCnt++;
        ui->labelCircleCnt->setText(QString("%1").arg(this->circleCnt));
    }
    if(this->rowNbr == this->rowCnt && this->rowCricle==false)
    {
        this->rowCricle=false;
        this->rowNbr = this->rowCnt;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        return;
    }
    script = this->tabModel->index(this->rowNbr,this->tabModel->fieldIndex("script")).data().toString();

    tJson json;
    if(!json.validateJson(script))
    {
        this->messageBox->warning(this,"警告",QString("测试终止\n第%1行:json脚本错误").arg(this->rowNbr));
        this->rowCricle=false;
        this->rowNbr = this->rowCnt;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        return;
    }
    this->scriptJson = json.jsonStringToDict(script);
    if(this->scriptJson["ignore"].toBool())
    {
        this->rowNbr++;
        goto IGNORE_LOOP;
    }
    //忽略空行
    sendBuf = this->tabModel->index(this->rowNbr,this->tabModel->fieldIndex("at_cmd")).data().toString();
    if(sendBuf.isEmpty())
    {
        this->rowNbr++;
        goto IGNORE_LOOP;
    }
/*******************IGNORE_LOOP end**********************/

    if(this->rowNbr < this->rowCnt)
    {
        delayms = this->tabModel->index(this->rowNbr,this->tabModel->fieldIndex("delayms")).data().toInt();
        if(caseLoopCnt[this->rowNbr]==0)
        {
            caseLoopCnt[this->rowNbr] = this->scriptJson["count"].toInt();
        }
        if(delayms>0)
        {
            on_itemClick(this->rowNbr);
        }
        this->timerSendNbr->singleShot(delayms,Qt::CoarseTimer,this,SLOT(on_timerSendNbr()));
        if(caseLoopCnt[this->rowNbr]==0)
        {
            this->rowNbr++;
        }
        else
        {
            caseLoopCnt[this->rowNbr]--;
            if(caseLoopCnt[this->rowNbr]==0)
            {
                this->rowNbr++;
            }
        }
    }
}
void MainWindow::on_timerSendCaseListTest()
{
    int delayms;
    QString script;
    QString sendBuf;
    static QMap<int,int> caseLoopCnt;

/*****************IGNORE_LOOP start************************/
IGNORE_LOOP:
    if(this->rowNbr == this->rowCnt && this->rowCaseTestList)
    {
        this->rowNbr = 0;
        int maxCount = ui->comboBoxTablesCase->count()-1;
        int curIndex = ui->comboBoxTablesCase->currentIndex();
        if(maxCount == curIndex)
        {
            this->rowCaseTestList=false;
            this->rowNbr = 0;
            this->rowCnt = 0;
            this->messageBox->information(this,"报告","用例测试完成");
            //保存测试报告
            QString extractTo = QCoreApplication::applicationDirPath();
            QString dirName = QDir::cleanPath(extractTo+QDir::separator()+".."+QDir::separator()+"caseTestReport"+QDir::separator()+this->dateTime->currentDateTime().toString("yyyyMMdd"));
            QDir dir(dirName);
            if (!dir.exists())
            {
                if(!dir.mkpath(dirName))
                {
                    qDebug()<<"日志目录创建失败";
                    return;
                }
            }
            this->xlsxDoc->saveAs(dirName+QDir::separator()+"测试报告_"+this->dateTime->currentDateTime().toString("yyyyMMddhhmmss")+".xlsx");
            ui->comboBoxTablesCase->setCurrentIndex(0);
            refreshTableView();
        }
        else
        {
            ui->comboBoxTablesCase->setCurrentIndex(curIndex+1);
            refreshTableView();
            this->rowCnt = this->tabModel->rowCount();

            //测试报告，增加一个sheet
            this->xlsxDoc->addSheet(ui->comboBoxTablesCase->currentText());
            this->xlsxDoc->selectSheet(ui->comboBoxTablesCase->currentText());
            QXlsx::Format bakgroundColor;
            bakgroundColor.setPatternBackgroundColor(Qt::blue);

            this->xlsxDoc->write(1,1,"名称",bakgroundColor);
            this->xlsxDoc->write(1,2,"命令",bakgroundColor);
            this->xlsxDoc->write(1,3,"期望返回值",bakgroundColor);
            this->xlsxDoc->write(1,4,"延时ms",bakgroundColor);
            this->xlsxDoc->write(1,5,"标志脚本",bakgroundColor);
            this->xlsxDoc->write(1,6,"实际返回值",bakgroundColor);
            this->xlsxDoc->write(1,7,"测试通过",bakgroundColor);
        }
    }
    if(this->rowNbr == this->rowCnt && this->rowCaseTestList==false)
    {
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        QIcon btnStartCaseTestIcon;
        btnStartCaseTestIcon.addFile(":/icons/icons/icons8-go-96.png");
        ui->btnStartCaseTest->setIcon(btnStartCaseTestIcon);
        return;
    }

    script = this->tabModel->index(this->rowNbr,this->tabModel->fieldIndex("script")).data().toString();
    tJson json;
    if(!json.validateJson(script))
    {
        this->messageBox->warning(this,"警告",QString("测试终止\n第%1行:json脚本错误").arg(this->rowNbr));
        this->rowCaseTestList=false;
        this->timerSend->stop();
        this->timerSendNbr->stop();
        ui->chkBoxSendCircle->setEnabled(true);
        ui->chkBoxTimerSend->setEnabled(true);
        ui->btnSendNbr->setEnabled(true);
        ui->lineEditTimerSendCycle->setEnabled(true);
        return;
    }
    this->scriptJson = json.jsonStringToDict(script);
    if(this->scriptJson["ignore"].toBool())
    {
        this->rowNbr++;
        goto IGNORE_LOOP;
    }
/*******************IGNORE_LOOP end**********************/

    if(this->rowNbr < this->rowCnt)
    {
        delayms = this->tabModel->index(this->rowNbr,this->tabModel->fieldIndex("delayms")).data().toInt();
        if(caseLoopCnt[this->rowNbr]==0)
        {
            caseLoopCnt[this->rowNbr] = this->scriptJson["count"].toInt();
        }
        if(delayms>0)
        {
            this->rowNbrCur = this->rowNbr;
            on_itemClick(this->rowNbr);
        }
        this->timerSendNbr->singleShot(delayms,Qt::CoarseTimer,this,SLOT(on_timerSendCaseListTest()));
        if(caseLoopCnt[this->rowNbr]==0)
        {
            this->rowNbr++;
        }
        else
        {
            caseLoopCnt[this->rowNbr]--;
            if(caseLoopCnt[this->rowNbr]==0)
            {
                this->rowNbr++;
            }
        }
    }
}



void MainWindow::on_chkBoxSendHex_clicked(bool checked)
{
    this->hexSendFlag = checked;
    if(checked)
    {
        ui->chkBoxAddReturn->setEnabled(false);
        QString curPlainText = ui->plainTextEditSend->toPlainText();
        curPlainText.replace("\n","\r\n");
        QByteArray ar = curPlainText.toLatin1().toHex();
        QString plainTextHex = QString::fromUtf8(ar);
        int n = plainTextHex.length();
        while(n-2>0)
        {
            n = n-2;
            plainTextHex.insert(n," ");
        }
        ui->plainTextEditSend->setPlainText(plainTextHex);
    }
    else
    {
        ui->chkBoxAddReturn->setEnabled(true);
        QString curPlainTextHex = ui->plainTextEditSend->toPlainText();
        curPlainTextHex.remove(" ");
        QByteArray ar = QByteArray::fromHex(curPlainTextHex.toLocal8Bit());
        QString plainText = QString::fromLatin1(ar);
        ui->plainTextEditSend->setPlainText(plainText);
    }
}

void MainWindow::on_btnAddTables_clicked()
{
    QString table = ui->lineEditTables->text();
    if(table.length()>0)
    {
        if(createModel(table))
        {
            ui->lineEditTables->clear();
            refreshTableView();
        }
    }
}


void MainWindow::on_btnDeleteTables_clicked()
{
    QString model_name = ui->lineEditTables->text();
    if(model_name.length()>0)
    {
        if(deleteModel(model_name))
        {
            ui->lineEditTables->clear();
            refreshTableView();
        }
    }
}


void MainWindow::on_btnRefreshTables_clicked()
{
    if(refreshRelationalTables())
    {
        refreshTableView();
    }
}

void MainWindow::on_menuHelpTriggered(QAction *action)
{
    if(action == ui->actionhelp)
    {
        // QUrl url(QString("https://lierda.feishu.cn/wiki/JRk6wrlcriCg1VkLRRdc74Xtnrm"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/nodes/MyQA2dXW7e7kn7ZLfrLv4wjmJzlwrZgb?utm_scene=person_space"));

        QDesktopServices::openUrl(url);
    }
    else if(action == ui->actionupgrade)
    {
        this->updateDialog->show();
        this->updateDialog->checkForUpdate();
    }
    else if(action == ui->actioninfo)
    {
        QMessageBox *msgBox = new QMessageBox();
        msgBox->setWindowTitle("软件信息");
        msgBox->setText("AT命令助手"+QString(TOOLSVERSION)+"\n\n问题反馈联系方式:\n作者:<王友峰>\n邮箱:wangyoufeng8889@126.com\n");
        // msgBox->setIconPixmap(QPixmap(":/icons/icons/weixin.png"));
        msgBox->exec();
    }
    else if(action == ui->actionswitchmode)
    {

        if(ui->actionswitchmode->text() == "进入测试报告模式")
        {
            ui->actionswitchmode->setText("退出测试报告模式");
            //进入测试报告模式
            ui->btnImportCaseListXlsx->show();
            ui->btnClearCaseList->show();
            ui->btnStartCaseTest->show();
            //禁用非测试报告模式操作
            ui->chkBoxSendCircle->hide();
            ui->btnSendNbr->hide();
            ui->btnAddTables->hide();
            ui->btnDeleteTables->hide();
            ui->btnRefreshTables->hide();
            ui->btnRenameTables->hide();

            ui->btnAddCell->hide();
            ui->btnInsertCell->hide();
            ui->btnRemoveCell->hide();
            ui->btnMoveUp->hide();
            ui->btnMoveDown->hide();
            ui->btnImportCaseXlsx->hide();
            ui->btnExportCaseXlsx->hide();

            ui->lineEditTables->hide();
            ui->labelCircleCnt->hide();


            //进入测试报告模式数据表
            this->tabModel->setTable("at_casetestinfo");
            QSqlQuery query(this->sqlitedb);
            if(query.exec(QString("SELECT * from case_casetestinfo;")))
            {
                ui->comboBoxTablesCase->clear();
                this->caseMap.clear();
                while(query.next())
                {
                    QString tableName = query.value(1).toString();
                    ui->comboBoxTablesCase->addItem(tableName);
                    this->caseMap[tableName] = query.value(0).toInt();
                }
                // comboBox_widthAdjust(ui->comboBoxTablesCase);
            }

        }
        else
        {
            ui->actionswitchmode->setText("进入测试报告模式");
            //退出测试报告模式
            ui->btnImportCaseListXlsx->hide();
            ui->btnClearCaseList->hide();
            ui->btnStartCaseTest->hide();
            //启用非测试报告模式操作
            ui->chkBoxSendCircle->show();
            ui->btnSendNbr->show();
            ui->btnAddTables->show();
            ui->btnDeleteTables->show();
            ui->btnRefreshTables->show();
            ui->btnRenameTables->show();

            ui->btnAddCell->show();
            ui->btnInsertCell->show();
            ui->btnRemoveCell->show();
            ui->btnMoveUp->show();
            ui->btnMoveDown->show();
            ui->btnImportCaseXlsx->show();
            ui->btnExportCaseXlsx->show();

            ui->lineEditTables->show();
            ui->labelCircleCnt->show();

            //退出测试报告模式数据表
            this->tabModel->setTable("at_info");
            QSqlQuery query(this->sqlitedb);
            if(query.exec(QString("SELECT * from case_info;")))
            {
                ui->comboBoxTablesCase->clear();
                this->caseMap.clear();
                while(query.next())
                {
                    QString tableName = query.value(1).toString();
                    ui->comboBoxTablesCase->addItem(tableName);
                    this->caseMap[tableName] = query.value(0).toInt();
                }
                // comboBox_widthAdjust(ui->comboBoxTablesCase);
            }
        }
        this->tabModel->setEditStrategy(QSqlTableModel::OnFieldChange);
        this->tabModel->setFilter(QString("case_id = %1").arg(this->caseMap[ui->comboBoxTablesCase->currentText()]));
        this->tabModel->setSort(this->tabModel->fieldIndex("at_id"),Qt::AscendingOrder);

        this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_id"), Qt::Horizontal, QObject::tr("发送"));
        this->tabModel->setHeaderData(this->tabModel->fieldIndex("remark"), Qt::Horizontal, QObject::tr("名称"));
        this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_cmd"), Qt::Horizontal, QObject::tr("命令"));
        this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_return"), Qt::Horizontal, QObject::tr("期望返回值"));
        this->tabModel->setHeaderData(this->tabModel->fieldIndex("delayms"), Qt::Horizontal, QObject::tr("延时ms"));
        this->tabModel->setHeaderData(this->tabModel->fieldIndex("script"), Qt::Horizontal, QObject::tr("标志脚本"));
        this->tabModel->select();
        ui->tableViewSqlite->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_id"),QHeaderView::Fixed);
        ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_id"),60);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("remark"),QHeaderView::Interactive);
        ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("remark"),120);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_cmd"),QHeaderView::Interactive);
        ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_cmd"),180);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_return"),QHeaderView::Interactive);
        ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_return"),180);
        ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("script"),QHeaderView::Interactive);
        ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("script"),120);

        ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("case_id"));
        ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("create_date"));
        ui->tableViewSqlite->show();
        ui->tableViewSqlite->setEditTriggers(QAbstractItemView::DoubleClicked);
    }
}

void MainWindow::on_menuProductTriggered(QAction *action)
{
    if(action == ui->actionCat_1)
    {
        // QUrl url(QString("https://lierda.feishu.cn/wiki/In16wuu6KiPfMNk5JI2cG7Pcngq"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/nodes/pYLaezmVNevBAvkwfBp3jP7DWrMqPxX6?utm_scene=team_space"));

        QDesktopServices::openUrl(url);
    }
    else if(action == ui->actionNB)
    {
        // QUrl url(QString("https://lierda.feishu.cn/wiki/AMk3werNWijcqrkQoqycLk43nre"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/nodes/1DKw2zgV2P7D273GsKZGnM058B5r9YAn?utm_scene=team_space"));
        QDesktopServices::openUrl(url);
    }
    else if(action == ui->action5G)
    {
        // QUrl url(QString("https://lierda.feishu.cn/wiki/Dz36w5b8wiJ6AekbwUIcTpv2nOb"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/nodes/pGBa2Lm8aGwnEwNDc5qdmjzmVgN7R35y?utm_scene=team_space"));
        QDesktopServices::openUrl(url);
    }
    else if(action == ui->actionNormal)
    {
        // QUrl url(QString("https://lierda.feishu.cn/wiki/O987wsyF4ijJihk9dCEcBsXBnPA"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/nodes/NDoBb60VLQKq6KkwC7ejRP4RJlemrZQ3?utm_scene=team_space"));
        QDesktopServices::openUrl(url);
    }
    else if(action == ui->actionfirmware)
    {
        // QUrl url(QString("https://lierda.feishu.cn/drive/folder/F2jxfWGSTlJ0iDdxm2ncWgXUnLh"));
        QUrl url(QString("https://alidocs.dingtalk.com/i/desktop/folders/KkdpYLaezmVNeZlDLkYIOWrMqPxX6R90"));
        QDesktopServices::openUrl(url);
    }
}


void MainWindow::on_btnOpenFile_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","All Files (*)",nullptr,QFileDialog::DontUseNativeDialog);
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile->setText(fileName);
        QTextStream in(&file);
        QString context = in.read(4096);
        ;
        ui->plainTextEditShowA->insertPlainText(QString("\nTip:文件大小:%1bytes,预览前:%2bytes\n").arg(file.size()).arg(context.size()));
        ui->plainTextEditShowA->insertPlainText(context);
        ui->plainTextEditShowA->moveCursor(QTextCursor::End);
        file.close();
    }
}


void MainWindow::on_btnSendFile_clicked()
{
    QString fileName = ui->lineEditFile->text();
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile->setText(fileName);
        QTextStream in(&file);
        QByteArray bts = in.readAll().toLocal8Bit();
        uartSend(bts);
        file.close();
    }
}
void MainWindow::on_btnOpenFile_2_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","All Files (*)",nullptr,QFileDialog::DontUseNativeDialog);
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_2->setText(fileName);
        QTextStream in(&file);
        QString context = in.readAll();
        ui->plainTextEditShowA->insertPlainText(QString("\nTip:文件大小:%1bytes,预览前:%2bytes\n").arg(file.size()).arg(context.size()));
        ui->plainTextEditShowA->insertPlainText(context);
        ui->plainTextEditShowA->moveCursor(QTextCursor::End);
        file.close();
    }
}


void MainWindow::on_btnSendFile_2_clicked()
{
    QString fileName = ui->lineEditFile_2->text();
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_2->setText(fileName);
        QTextStream in(&file);
        QByteArray bts = in.readAll().toLocal8Bit();
        uartSend(bts);
        file.close();
    }
}
void MainWindow::on_btnOpenFile_3_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","All Files (*)",nullptr,QFileDialog::DontUseNativeDialog);
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_3->setText(fileName);
        QTextStream in(&file);
        QString context = in.readAll();
        ui->plainTextEditShowA->insertPlainText(QString("\nTip:文件大小:%1bytes,预览前:%2bytes\n").arg(file.size()).arg(context.size()));
        ui->plainTextEditShowA->insertPlainText(context);
        ui->plainTextEditShowA->moveCursor(QTextCursor::End);
        file.close();
    }
}


void MainWindow::on_btnSendFile_3_clicked()
{
    QString fileName = ui->lineEditFile_3->text();
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_3->setText(fileName);
        QTextStream in(&file);
        QByteArray bts = in.readAll().toLocal8Bit();
        uartSend(bts);
        file.close();
    }
}
void MainWindow::on_btnOpenFile_4_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","All Files (*)",nullptr,QFileDialog::DontUseNativeDialog);
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_4->setText(fileName);
        QTextStream in(&file);
        QString context = in.readAll();
        ui->plainTextEditShowA->insertPlainText(QString("\nTip:文件大小:%1bytes,预览前:%2bytes\n").arg(file.size()).arg(context.size()));
        ui->plainTextEditShowA->insertPlainText(context);
        ui->plainTextEditShowA->moveCursor(QTextCursor::End);
        file.close();
    }
}


void MainWindow::on_btnSendFile_4_clicked()
{
    QString fileName = ui->lineEditFile_4->text();
    if(!fileName.isEmpty())
    {
        QFile file(fileName);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            this->messageBox->warning(this,"警告","文件打开失败\n"+fileName);
            return;
        }
        ui->lineEditFile_4->setText(fileName);
        QTextStream in(&file);
        QByteArray bts = in.readAll().toLocal8Bit();
        uartSend(bts);
        file.close();
    }
}

void MainWindow::on_btnOpenCompareTools_clicked()
{
    QString extractTo = QCoreApplication::applicationDirPath();
    QString dirName = QDir::cleanPath(extractTo+QDir::separator()+".."+QDir::separator()+"log");
    QDir dir(dirName);
    if (!dir.exists())
    {
        if(!dir.mkdir(dirName))
        {
            this->messageBox->warning(this,"警告","日志目录创建失败");
            return;
        }
    }
    QDesktopServices::openUrl(QUrl::fromLocalFile(dirName));
    QString winmerge = QDir::cleanPath(extractTo+QDir::separator()+".."+QDir::separator()+"WinMerge"+QDir::separator()+"WinMergeU.exe");
    QProcess::startDetached(winmerge);
}



//"A:ASCII"<<"A:ASCII&HEX"<<"B:ASCII&HEX"<<"A:ASCII&B:ASCII"<<"A:HEX&&B:HEX"<<"A:ASCII&HEX&&B:ASCII&HEX";
void MainWindow::on_comboBoxCompare_activated(int index)
{
    switch(index)
    {
    case 0:
        ui->plainTextEditShowA->show();
        ui->plainTextEditShowHexA->hide();
        ui->plainTextEditShowB->hide();
        ui->plainTextEditShowHexB->hide();
        break;
    case 1:
        ui->plainTextEditShowA->show();
        ui->plainTextEditShowHexA->show();
        ui->plainTextEditShowB->hide();
        ui->plainTextEditShowHexB->hide();
        break;
    case 2:
        ui->plainTextEditShowA->hide();
        ui->plainTextEditShowHexA->hide();
        ui->plainTextEditShowB->show();
        ui->plainTextEditShowHexB->show();
        break;
    case 3:
        ui->plainTextEditShowA->show();
        ui->plainTextEditShowHexA->hide();
        ui->plainTextEditShowB->show();
        ui->plainTextEditShowHexB->hide();
        break;
    case 4:
        ui->plainTextEditShowA->hide();
        ui->plainTextEditShowHexA->show();
        ui->plainTextEditShowB->hide();
        ui->plainTextEditShowHexB->show();
        break;
    case 5:
        ui->plainTextEditShowA->show();
        ui->plainTextEditShowHexA->show();
        ui->plainTextEditShowB->show();
        ui->plainTextEditShowHexB->show();
        break;
    }
}


void MainWindow::on_comboBoxTablesCase_activated(int index)
{
    Q_UNUSED(index);
    refreshTableView();
}




void MainWindow::on_comboBoxTablesModel_activated(int index)
{
    Q_UNUSED(index);
    if(refreshRelationalTables())
    {
        refreshTableView();
    }
}


void MainWindow::on_comboBoxTablesFunc_activated(int index)
{
    Q_UNUSED(index);
    if(refreshRelationalTables())
    {
        refreshTableView();
    }
}



void MainWindow::on_btnRenameTables_clicked()
{
    if(ui->lineEditTables->text().length()<3)
    {
        this->messageBox->warning(this,"警告","请输入合适的case名称，不少于3位");
        return;
    }
    QSqlQuery query;
    QString sql;

    query = QSqlQuery(this->sqlitedb);

    sql = QString("UPDATE case_info SET case_name = '%1' WHERE case_id = %2;").arg(ui->lineEditTables->text()).arg(this->caseMap[ui->comboBoxTablesCase->currentText()]);
    log(INFO,sql);
    if(query.exec(sql))
    {
        log(INFO,"update ok");
        this->caseMap[ui->lineEditTables->text()]=this->caseMap[ui->comboBoxTablesCase->currentText()];
        this->caseMap.remove(ui->comboBoxTablesCase->currentText());
        ui->comboBoxTablesCase->addItem(ui->lineEditTables->text());
        ui->comboBoxTablesCase->removeItem(ui->comboBoxTablesCase->currentIndex());
        ui->comboBoxTablesCase->setCurrentText(ui->lineEditTables->text());
        ui->lineEditTables->clear();
    }
    else
    {
        log(INFO,"update fail");
        this->messageBox->warning(this,"警告","重命名失败");
    }
}

void MainWindow::on_chkBoxAddRxTx_clicked(bool checked)
{
    this->addRxTxFlag = checked;
}


void MainWindow::on_btnMoveDown_clicked()
{
    int row,maxrow;
    int currow_id,currow_id_down;
    QModelIndex curIdex;
    row = this->selModel->currentIndex().row();
    maxrow = this->tabModel->rowCount();
    if(row<0)
    {
        this->messageBox->warning(this,"警告","请选定要移动的行");
        return;
    }
    if(row==(maxrow-1))
    {
        this->messageBox->warning(this,"警告","已移动到最后一行");
        return;
    }
    currow_id =  this->tabModel->index(row,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
    currow_id_down =  this->tabModel->index(row+1,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();

    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("at_id")),0);
    this->tabModel->setData(this->tabModel->index(row+1,this->tabModel->fieldIndex("at_id")),currow_id);
    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("at_id")),currow_id_down);

    this->tabModel->submitAll();
    this->tabModel->select();
    this->selModel->setCurrentIndex(this->tabModel->index(row+1,this->tabModel->fieldIndex("remark")),QItemSelectionModel::Select);
}


void MainWindow::on_btnMoveUp_clicked()
{
    int row;
    int currow_id,currow_id_up;
    QModelIndex curIdex;

    row = this->selModel->currentIndex().row();
    if(row<0)
    {
        this->messageBox->warning(this,"警告","请选定要移动的行");
        return;
    }
    if(row==0)
    {
        this->messageBox->warning(this,"警告","已移动到第一行");
        return;
    }
    currow_id =  this->tabModel->index(row,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
    currow_id_up =  this->tabModel->index(row-1,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();

    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("at_id")),0);
    this->tabModel->setData(this->tabModel->index(row-1,this->tabModel->fieldIndex("at_id")),currow_id);
    this->tabModel->setData(this->tabModel->index(row,this->tabModel->fieldIndex("at_id")),currow_id_up);

    this->tabModel->submitAll();
    this->tabModel->select();
    this->selModel->setCurrentIndex(this->tabModel->index(row-1,this->tabModel->fieldIndex("remark")),QItemSelectionModel::Select);
}

void MainWindow::on_btnExportCaseXlsx_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this,"保存为","","*.xlsx",nullptr,QFileDialog::DontUseNativeDialog);
    if(fileName.isEmpty())
    {
        this->messageBox->warning(this,"警告","Xlsx文件不存在");
        return;
    }
    qDebug()<<"fileName"<<fileName;
    QXlsx::Document xlsxDoc(fileName);
    QVariant writeValue;
    QXlsx::Format bakgroundColor;
    bakgroundColor.setPatternBackgroundColor(Qt::blue);

    xlsxDoc.write(1,1,"名称",bakgroundColor);
    xlsxDoc.write(1,2,"命令",bakgroundColor);
    xlsxDoc.write(1,3,"期望返回值",bakgroundColor);
    xlsxDoc.write(1,4,"延时ms",bakgroundColor);
    xlsxDoc.write(1,5,"标志脚本",bakgroundColor);

    xlsxDoc.renameSheet("Sheet1",ui->comboBoxTablesCase->currentText());
    int maxrow = this->tabModel->rowCount();
    for(int row=0;row<maxrow;row++)
    {
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("remark")).data(Qt::DisplayRole).toString();
        xlsxDoc.write(row+2,1,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("at_cmd")).data(Qt::DisplayRole).toString();
        xlsxDoc.write(row+2,2,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("at_return")).data(Qt::DisplayRole).toString();
        xlsxDoc.write(row+2,3,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("delayms")).data(Qt::DisplayRole).toInt();
        xlsxDoc.write(row+2,4,writeValue);
        writeValue =  this->tabModel->index(row,this->tabModel->fieldIndex("script")).data(Qt::DisplayRole).toString();
        xlsxDoc.write(row+2,5,writeValue);
    }
    xlsxDoc.saveAs(fileName.append(".xlsx"));
}

void MainWindow::on_btnImportCaseXlsx_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","*.xlsx",nullptr,QFileDialog::DontUseNativeDialog);
    if(fileName.isEmpty())
    {
        this->messageBox->warning(this,"警告","Xlsx文件不存在");
        return;
    }
    qDebug()<<"fileName"<<fileName;
    QXlsx::Document xlsxDoc(fileName);
    if(!xlsxDoc.isLoadPackage())
    {
        qDebug() << fileName << "failed to load package";
        return;
    }
    int sheetIndexNumber = 0;
    QSqlQuery query;
    QString sql;
    int at_id;
    foreach( QString currentSheetName, xlsxDoc.sheetNames() )
    {
        // get current sheet
        QXlsx::AbstractSheet* currentSheet = xlsxDoc.sheet( currentSheetName );
        if ( NULL == currentSheet )
            continue;

        // get full cells of current sheet
        int maxRow = -1;
        int maxCol = -1;
        currentSheet->workbook()->setActiveSheet( sheetIndexNumber );
        QXlsx::Worksheet* wsheet = (QXlsx::Worksheet*) currentSheet->workbook()->activeSheet();
        if ( NULL == wsheet )
            continue;

        QString strSheetName = wsheet->sheetName(); // sheet name
        qDebug() << strSheetName;
        if(strSheetName == "说明文档")
        {
            sheetIndexNumber++;
            continue;
        }
        QVector<QXlsx::CellLocation> clList = wsheet->getFullCells( &maxRow, &maxCol );

        QVector< QVector<QString> > cellValues;
        for (int rc = 0; rc < maxRow; rc++)
        {
            QVector<QString> tempValue;
            for (int cc = 0; cc < maxCol; cc++)
            {
                tempValue.push_back(QString(""));
            }
            cellValues.push_back(tempValue);
        }

        for ( int ic = 0; ic < clList.size(); ++ic )
        {
            QXlsx::CellLocation cl = clList.at(ic); // cell location

            int row = cl.row - 1;
            int col = cl.col - 1;

            // QSharedPointer<QXlsx::Cell> ptrCell = cl.cell; // cell pointer
            std::shared_ptr<QXlsx::Cell> ptrCell = cl.cell; // cell pointer

            // value of cell
            QVariant var = ptrCell->value();
            QString str = var.toString();

            cellValues[row][col] = str;
        }

        query = QSqlQuery(this->sqlitedb);
        int maxrow = this->tabModel->rowCount();
        at_id =  this->tabModel->index(maxrow-1,this->tabModel->fieldIndex("at_id")).data(Qt::DisplayRole).toInt();
        at_id++;
        for (int rc = 1; rc < maxRow; rc++)
        {
            if(cellValues[rc][4] == nullptr)
            {
                continue;
            }
            QString text = cellValues[rc][2];
            text.replace("\n","\r\n");
            sql = QString("INSERT INTO at_info(at_id,remark,at_cmd,at_return,delayms,script,case_id) \
                             VALUES(%1,'%2','%3','%4',%5,'%6',%7);").arg(at_id).arg(cellValues[rc][0]).arg(cellValues[rc][1]).arg(text).arg(cellValues[rc][3]).arg(cellValues[rc][4]).arg(this->caseMap[ui->comboBoxTablesCase->currentText()]);

            log(INFO,sql);
            if(query.exec(sql))
            {
                log(INFO,"inert ok");
                at_id++;
            }
            else
            {
                log(INFO,"inert fail");
            }
        }
        this->tabModel->select();

        break;
    }
}

void MainWindow::on_chkBoxCaseReport_stateChanged(int arg1)
{
    if(arg1)
    {
        //进入测试报告模式
        ui->btnImportCaseListXlsx->show();
        ui->btnClearCaseList->show();
        ui->btnStartCaseTest->show();
        //禁用非测试报告模式操作
        ui->chkBoxSendCircle->hide();
        ui->btnSendNbr->hide();
        ui->btnAddTables->hide();
        ui->btnDeleteTables->hide();
        ui->btnRefreshTables->hide();
        ui->btnRenameTables->hide();

        ui->btnAddCell->hide();
        ui->btnInsertCell->hide();
        ui->btnRemoveCell->hide();
        ui->btnMoveUp->hide();
        ui->btnMoveDown->hide();
        ui->btnImportCaseXlsx->hide();
        ui->btnExportCaseXlsx->hide();

        ui->lineEditTables->hide();
        ui->labelCircleCnt->hide();


        //进入测试报告模式数据表
        this->tabModel->setTable("at_casetestinfo");
        QSqlQuery query(this->sqlitedb);
        if(query.exec(QString("SELECT * from case_casetestinfo;")))
        {
            ui->comboBoxTablesCase->clear();
            this->caseMap.clear();
            while(query.next())
            {
                QString tableName = query.value(1).toString();
                ui->comboBoxTablesCase->addItem(tableName);
                this->caseMap[tableName] = query.value(0).toInt();
            }
            // comboBox_widthAdjust(ui->comboBoxTablesCase);
        }

    }
    else
    {
        //退出测试报告模式
        ui->btnImportCaseListXlsx->hide();
        ui->btnClearCaseList->hide();
        ui->btnStartCaseTest->hide();
        //启用非测试报告模式操作
        ui->chkBoxSendCircle->show();
        ui->btnSendNbr->show();
        ui->btnAddTables->show();
        ui->btnDeleteTables->show();
        ui->btnRefreshTables->show();
        ui->btnRenameTables->show();

        ui->btnAddCell->show();
        ui->btnInsertCell->show();
        ui->btnRemoveCell->show();
        ui->btnMoveUp->show();
        ui->btnMoveDown->show();
        ui->btnImportCaseXlsx->show();
        ui->btnExportCaseXlsx->show();

        ui->lineEditTables->show();
        ui->labelCircleCnt->show();

        //退出测试报告模式数据表
        this->tabModel->setTable("at_info");
        QSqlQuery query(this->sqlitedb);
        if(query.exec(QString("SELECT * from case_info;")))
        {
            ui->comboBoxTablesCase->clear();
            this->caseMap.clear();
            while(query.next())
            {
                QString tableName = query.value(1).toString();
                ui->comboBoxTablesCase->addItem(tableName);
                this->caseMap[tableName] = query.value(0).toInt();
            }
            // comboBox_widthAdjust(ui->comboBoxTablesCase);
        }
    }
    this->tabModel->setEditStrategy(QSqlTableModel::OnFieldChange);
    this->tabModel->setFilter(QString("case_id = %1").arg(this->caseMap[ui->comboBoxTablesCase->currentText()]));
    this->tabModel->setSort(this->tabModel->fieldIndex("at_id"),Qt::AscendingOrder);

    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_id"), Qt::Horizontal, QObject::tr("发送"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("remark"), Qt::Horizontal, QObject::tr("名称"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_cmd"), Qt::Horizontal, QObject::tr("命令"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("at_return"), Qt::Horizontal, QObject::tr("期望返回值"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("delayms"), Qt::Horizontal, QObject::tr("延时ms"));
    this->tabModel->setHeaderData(this->tabModel->fieldIndex("script"), Qt::Horizontal, QObject::tr("标志脚本"));
    this->tabModel->select();
    ui->tableViewSqlite->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_id"),QHeaderView::Fixed);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_id"),60);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("remark"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("remark"),120);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_cmd"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_cmd"),180);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("at_return"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("at_return"),180);
    ui->tableViewSqlite->horizontalHeader()->setSectionResizeMode(this->tabModel->fieldIndex("script"),QHeaderView::Interactive);
    ui->tableViewSqlite->setColumnWidth(this->tabModel->fieldIndex("script"),120);

    ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("case_id"));
    ui->tableViewSqlite->hideColumn(this->tabModel->fieldIndex("create_date"));
    ui->tableViewSqlite->show();
    ui->tableViewSqlite->setEditTriggers(QAbstractItemView::DoubleClicked);
}


void MainWindow::on_btnImportCaseListXlsx_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开文件","","*.xlsx",nullptr,QFileDialog::DontUseNativeDialog);
    if(fileName.isEmpty())
    {
        this->messageBox->warning(this,"警告","Xlsx文件不存在");
        return;
    }
    qDebug()<<"fileName"<<fileName;
    QXlsx::Document xlsxDoc(fileName);
    if(!xlsxDoc.isLoadPackage())
    {
        qDebug() << fileName << "failed to load package";
        return;
    }
    int sheetIndexNumber = 0;
    QSqlQuery query(this->sqlitedb);
    QString sql;
    int at_id=1;
    int case_id=1;
    foreach( QString currentSheetName, xlsxDoc.sheetNames() )
    {
        // get current sheet
        QXlsx::AbstractSheet* currentSheet = xlsxDoc.sheet( currentSheetName );
        if ( NULL == currentSheet )
            continue;
        if(currentSheetName == "说明文档" || currentSheetName == "临时测试用例")
        {
            sheetIndexNumber++;
            continue;
        }

        // get full cells of current sheet
        int maxRow = -1;
        int maxCol = -1;
        currentSheet->workbook()->setActiveSheet( sheetIndexNumber );
        QXlsx::Worksheet* wsheet = (QXlsx::Worksheet*) currentSheet->workbook()->activeSheet();
        if ( NULL == wsheet )
            continue;

        QString strSheetName = wsheet->sheetName(); // sheet name
        qDebug() << strSheetName;
        QVector<QXlsx::CellLocation> clList = wsheet->getFullCells( &maxRow, &maxCol );

        QVector< QVector<QString> > cellValues;
        for (int rc = 0; rc < maxRow; rc++)
        {
            QVector<QString> tempValue;
            for (int cc = 0; cc < maxCol; cc++)
            {
                tempValue.push_back(QString(""));
            }
            cellValues.push_back(tempValue);
        }

        for ( int ic = 0; ic < clList.size(); ++ic )
        {
            QXlsx::CellLocation cl = clList.at(ic); // cell location

            int row = cl.row - 1;
            int col = cl.col - 1;

            // QSharedPointer<QXlsx::Cell> ptrCell = cl.cell; // cell pointer
            std::shared_ptr<QXlsx::Cell> ptrCell = cl.cell; // cell pointer

            // value of cell
            QVariant var = ptrCell->value();
            QString str = var.toString();

            cellValues[row][col] = str;
        }

        //插入case id

        sql = QString("INSERT INTO case_casetestinfo(case_id,case_name) \
                         VALUES(%1,'%2');").arg(case_id).arg(strSheetName);
        log(INFO,sql);
        if(query.exec(sql))
        {
            log(INFO,"inert ok");
        }
        else
        {
            log(INFO,"inert fail");
            this->messageBox->warning(this,"警告","case id导入失败");
            return;
        }

        //插入case AT
        for (int rc = 1; rc < maxRow; rc++)
        {
            if(cellValues[rc][4] == nullptr)
            {
                continue;
            }
            QString text = cellValues[rc][2];
            text.replace("\n","\r\n");
            sql = QString("INSERT INTO at_casetestinfo(at_id,remark,at_cmd,at_return,delayms,script,case_id) \
                             VALUES(%1,'%2','%3','%4',%5,'%6',%7);").arg(at_id).arg(cellValues[rc][0]).arg(cellValues[rc][1]).arg(text).arg(cellValues[rc][3]).arg(cellValues[rc][4]).arg(case_id);

            log(INFO,sql);
            if(query.exec(sql))
            {
                log(INFO,"inert ok");
                at_id++;
            }
            else
            {
                log(INFO,"inert fail");
                this->messageBox->warning(this,"警告","case at cmd导入失败");
                return;
            }
        }
        //准备下一个sheett
        sheetIndexNumber++;
        case_id++;
        at_id=1;
    }
    if(query.exec(QString("SELECT * from case_casetestinfo;")))
    {
        ui->comboBoxTablesCase->clear();
        this->caseMap.clear();
        while(query.next())
        {
            QString tableName = query.value(1).toString();
            ui->comboBoxTablesCase->addItem(tableName);
            this->caseMap[tableName] = query.value(0).toInt();
        }
        // comboBox_widthAdjust(ui->comboBoxTablesCase);
    }
    refreshTableView();
}


void MainWindow::on_btnClearCaseList_clicked()
{
    QSqlQuery query(this->sqlitedb);
    query.exec("delete from at_casetestinfo;");
    query.exec("delete from case_casetestinfo;");
    ui->comboBoxTablesCase->clear();
    this->caseMap.clear();
    refreshTableView();
    this->tabModel->select();
}


void MainWindow::on_btnStartCaseTest_clicked()
{
    if(!this->serialStateA && !this->serialStateA)
    {
        this->messageBox->warning(this,"警告","串口未打开");
        return;
    }
    if(this->rowCaseTestList)
    {
        this->rowCaseTestList=false;
        this->rowNbr = 0;
        this->rowCnt = 0;
        return;
    }

    this->rowCnt = this->tabModel->rowCount();
    if(this->rowCnt==0)
    {
        return ;
    }
    QIcon btnStartCaseTestIcon;
    btnStartCaseTestIcon.addFile(":/icons/icons/icons8-stop-sign-96.png");
    ui->btnStartCaseTest->setIcon(btnStartCaseTestIcon);

    this->timerSend->stop();
    ui->btnSendNbr->setEnabled(true);
    ui->chkBoxSendCircle->setEnabled(false);
    ui->chkBoxTimerSend->setEnabled(false);
    //启动测试
    this->rowNbr=0;
    this->rowCaseTestList=true;
    //准备报告文件
    this->xlsxDoc = new QXlsx::Document;
    // QVariant writeValue;
    QXlsx::Format bakgroundColor;
    bakgroundColor.setPatternBackgroundColor(Qt::blue);

    this->xlsxDoc->write(1,1,"名称",bakgroundColor);
    this->xlsxDoc->write(1,2,"命令",bakgroundColor);
    this->xlsxDoc->write(1,3,"期望返回值",bakgroundColor);
    this->xlsxDoc->write(1,4,"延时ms",bakgroundColor);
    this->xlsxDoc->write(1,5,"标志脚本",bakgroundColor);
    this->xlsxDoc->write(1,6,"实际返回值",bakgroundColor);
    this->xlsxDoc->write(1,7,"测试通过",bakgroundColor);

    this->xlsxDoc->renameSheet("Sheet1",ui->comboBoxTablesCase->currentText());
    this->timerSendNbr->singleShot(1,Qt::CoarseTimer,this,SLOT(on_timerSendCaseListTest()));
}

